<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Explorer. Dream. Discover.</title>
  
  
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://blog.samuelchen.net/"/>
  <updated>2022-02-03T19:26:34.930Z</updated>
  <id>http://blog.samuelchen.net/</id>
  
  <author>
    <name>Samuel Chen</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>2021年静态站生成与部署相关的服务和框架</title>
    <link href="http://blog.samuelchen.net/static-site-generation-framework-and-host-service-in-2021/"/>
    <id>http://blog.samuelchen.net/static-site-generation-framework-and-host-service-in-2021/</id>
    <published>2021-02-19T16:37:37.000Z</published>
    <updated>2022-02-03T19:26:34.930Z</updated>
    
    <content type="html"><![CDATA[<p>之前一直用Hugo 和 Hexo 来生成个人网站和博客，今天无意发现了一些新的服务和框架可<br>以用来部署或者生成静态网站，加上react 和一些serverless服务，几乎可以完整的建立<br>动态站。 这里记录一下。</p><ul><li><p><a href="https://nextjs.org/" target="_blank" rel="noopener">Next.js</a> - “生产级别的 React 的框架”<br>  支持很多开发者方便的特性,可以静态生成或者动态服务端生成</p></li><li><p><a href="https://www.gatsbyjs.com/" target="_blank" rel="noopener">Gatsby</a> - “一个前端搞定一切”<br>  号称非常快，可用于创建<strong>完整站点</strong>。</p></li><li><p><a href="https://forestry.io/" target="_blank" rel="noopener">Forestry</a> - 无头CMS<br>  直接在Git仓库上编辑内容，可以触发工作流编译部署</p></li><li><p><a href="https://www.netlify.com/" target="_blank" rel="noopener">Netlify</a> -  “基于Git的工作流, 函数计算平台”<br>  直接从Git仓库创建站点/服务，push触发工作流编译部署，函数计算服务</p></li><li><p><a href="https://vercel.com/" target="_blank" rel="noopener">Vercel</a> - “NextJS 家的部署平台”<br>  可以部署各种静态站，或者后端为NextJS的动态站。自动HTTPS及CDN。</p></li><li><p>其他 CMS</p><ul><li><a href="https://www.contentful.com/" target="_blank" rel="noopener">Contentful</a> - 企业级现代CMS</li><li><a href="https://www.sanity.io/" target="_blank" rel="noopener">Sanity</a> - 现代在线CMS，支持合作</li><li><a href="https://www.storyblok.com/" target="_blank" rel="noopener">StoryBlok</a> - 无头 CMS</li><li><a href="https://prismic.io/" target="_blank" rel="noopener">Prismic</a> - 无头 CMS，支持 GraphQL</li></ul></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;之前一直用Hugo 和 Hexo 来生成个人网站和博客，今天无意发现了一些新的服务和框架可&lt;br&gt;以用来部署或者生成静态网站，加上react 和一些serverless服务，几乎可以完整的建立&lt;br&gt;动态站。 这里记录一下。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=
      
    
    </summary>
    
      <category term="Utility" scheme="http://blog.samuelchen.net/categories/Utility/"/>
    
    
      <category term="static" scheme="http://blog.samuelchen.net/tags/static/"/>
    
      <category term="Hexo" scheme="http://blog.samuelchen.net/tags/Hexo/"/>
    
      <category term="Hugo" scheme="http://blog.samuelchen.net/tags/Hugo/"/>
    
      <category term="Next.js" scheme="http://blog.samuelchen.net/tags/Next-js/"/>
    
      <category term="Gatsby" scheme="http://blog.samuelchen.net/tags/Gatsby/"/>
    
      <category term="Forestry" scheme="http://blog.samuelchen.net/tags/Forestry/"/>
    
      <category term="Headless" scheme="http://blog.samuelchen.net/tags/Headless/"/>
    
      <category term="CMS" scheme="http://blog.samuelchen.net/tags/CMS/"/>
    
      <category term="react.js" scheme="http://blog.samuelchen.net/tags/react-js/"/>
    
  </entry>
  
  <entry>
    <title>解决重设树莓派 Raspbian 8 密码碰到的问题</title>
    <link href="http://blog.samuelchen.net/solve-problem-while-reseting-raspberry-raspbian-8-password/"/>
    <id>http://blog.samuelchen.net/solve-problem-while-reseting-raspberry-raspbian-8-password/</id>
    <published>2020-06-23T09:43:14.000Z</published>
    <updated>2022-02-03T19:26:34.930Z</updated>
    
    <content type="html"><![CDATA[<p>最近想把吃灰的<code>树莓派3B</code>拿出来用用，接通后却发现忘了密码，于是这网上找了些方法重置。</p><p>基本上都是这个步骤</p><ol><li>SD卡拿电脑上修改<code>cmdline.txt</code>，应该只有一行，在最后加上<code>init=/init/sh</code>，启动中途进入<code>shell</code>，也有用<code>bash</code>的。</li><li><p>SD卡插回树莓派，插电启动，然后等命令行输入：</p> <figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mount -o remount, rw /</span><br><span class="line">passwd pi</span><br></pre></td></tr></table></figure><p> 其中第一行是重新挂载，第二行是修改密码。</p></li><li><p>同步并初始化</p> <figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sync</span><br><span class="line"><span class="built_in">exec</span> /sbin/init</span><br></pre></td></tr></table></figure></li><li><p>关机 <code>sudo halt</code></p></li><li>编辑 <code>cmdline.txt</code> 去掉刚加入的内容。</li></ol><p>然后就可用正常启动了。</p><p>实际上，在重置的过程中，可能因为不同系统版本的原因，发生各种问题，如无法挂载，无法修改密码等。下面记录下碰到的问题及解决办法：</p><ol><li><p><code>mount -o remount, rw /</code> 命令报错 <code>mount: /: mount failed Unkown error -1</code></p><p>原因是启动的是<code>shell</code>不是<code>bash</code>，命令格式不同，在bash里正常，这里 <code>remount,</code> 和 <code>rw</code> 之间<strong>不要空格</strong>。</p></li><li><p>mount 错误 <code>mount: can&#39;t find PARTUUID=c903fbc0-02</code></p><p> 原因是UUID对应分区无法找到。先查看fstab（非必须） <code>cat /etc/fstab</code>，可用看到这个UUID对应的就是<code>/</code>。然后 <code>ls /dev/mmcblk*</code> 查看所有 mmc block 分区，可用看到对应的 <code>/dev/mmcblk0p2</code>。 最后，解决办法是，直接使用分区设备挂载 <code>mount -o remount,rw /dev/mmcblk0p2 /</code></p></li><li><p>修改密码时报错，<code>Authentication token manipulation error</code>。这是因为没有重新挂载，还是只读的原因，挂载成功就没这个问题。</p></li></ol><p>— END —</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;最近想把吃灰的&lt;code&gt;树莓派3B&lt;/code&gt;拿出来用用，接通后却发现忘了密码，于是这网上找了些方法重置。&lt;/p&gt;
&lt;p&gt;基本上都是这个步骤&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;SD卡拿电脑上修改&lt;code&gt;cmdline.txt&lt;/code&gt;，应该只有一行，在最后加上&lt;code
      
    
    </summary>
    
      <category term="Utility" scheme="http://blog.samuelchen.net/categories/Utility/"/>
    
    
      <category term="RaspBerry" scheme="http://blog.samuelchen.net/tags/RaspBerry/"/>
    
      <category term="Raspbian" scheme="http://blog.samuelchen.net/tags/Raspbian/"/>
    
      <category term="reset" scheme="http://blog.samuelchen.net/tags/reset/"/>
    
  </entry>
  
  <entry>
    <title>Architecture for Distributed Python/Django/Worker Applications.</title>
    <link href="http://blog.samuelchen.net/architecture-for-distributed-python-django-worker-applications/"/>
    <id>http://blog.samuelchen.net/architecture-for-distributed-python-django-worker-applications/</id>
    <published>2020-06-16T15:30:52.000Z</published>
    <updated>2022-02-03T19:26:34.930Z</updated>
    
    <content type="html"><![CDATA[<p>This is the architecture I designed for service “Managed Service for Alibaba Cloud” of company production. It’s also my common architecture that can be used to deploy distributed Python applications or service based on workers or MQ. This is a easy to upgrade architecture. You can simply add other service or make it becoming microservices.</p><a id="more"></a><p>I removed some sensitive information such as source code, configuration and so on.</p><h2 id="Requirements"><a href="#Requirements" class="headerlink" title="Requirements"></a>Requirements</h2><ul><li>OS - Linux (CentOS 7 or 6, Ubuntu ..)</li><li>Python 3.6 (&lt; 3.7) with pip, virtualenv …</li><li>gunicorn</li><li>nginx</li><li>supervisor (if need)</li><li>DB - Postgresql (or MySQL)</li><li>Task Queue - Redis (or RabbitMQ)</li><li>source code - Removed</li></ul><h2 id="Install"><a href="#Install" class="headerlink" title="Install"></a>Install</h2><pre><code>Removed</code></pre><h2 id="Setup-API"><a href="#Setup-API" class="headerlink" title="Setup API"></a>Setup API</h2><pre><code>Removed</code></pre><h2 id="Architect"><a href="#Architect" class="headerlink" title="Architect"></a>Architect</h2><p>Note: </p><ul><li><em>Nginx can be extracted on top of all boxes.</em> </li><li>Stack Files can be stored in individual box or OSS.</li><li>For now, Celery Worker must be in API Box (for HA, should no related to API. such as create/access)</li></ul><figure class="highlight gherkin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">                                Client APP</span><br><span class="line">                                     |</span><br><span class="line"><span class="string"> ----------------------------- LB / Firewall --------------------------------</span></span><br><span class="line"><span class="string">                                     </span>|</span><br><span class="line">                                    /|<span class="string">\</span></span><br><span class="line"><span class="string">            _________cross_________/ </span>|<span class="string"> \_________zone___________</span></span><br><span class="line"><span class="string">           </span>|<span class="string">                         </span>|<span class="string">                          </span>|</span><br><span class="line">       API Box 1/M              API Worker Box 1/N           APP Box 2/M        </span><br><span class="line"> ----------------------     ----------------------    ---------------------- </span><br><span class="line">|<span class="string">        Nginx         </span>|<span class="string">   </span>|<span class="string">        Celery        </span>|<span class="string">  </span>|<span class="string">        Nginx         </span>|</span><br><span class="line">|<span class="string">          </span>|<span class="string">           </span>|<span class="string">   </span>|<span class="string">          </span>|<span class="string">           </span>|<span class="string">  </span>|<span class="string">          </span>|<span class="string">           </span>|</span><br><span class="line">|<span class="string">         / \          </span>|<span class="string">   </span>|<span class="string">       N Workers      </span>|<span class="string">  </span>|<span class="string">         / \          </span>|</span><br><span class="line">|<span class="string">  Static   Gunicorn   </span>|<span class="string">   </span>|<span class="string">  _________</span>|<span class="string">________  </span>|<span class="string">  </span>|<span class="string">  Static   Gunicorn   </span>|</span><br><span class="line">|<span class="string">  Files       </span>|<span class="string">       </span>|<span class="string">   </span>|<span class="string">  </span>|<span class="string">     </span>|<span class="string">     </span>|<span class="string">    </span>|<span class="string">  </span>|<span class="string">  </span>|<span class="string">  Files       </span>|<span class="string">       </span>|</span><br><span class="line">|<span class="string">          N Workers   </span>|<span class="string">   </span>|<span class="string"> ...   ...    </span>|<span class="string">   ... </span>|<span class="string">  </span>|<span class="string">          N Workers   </span>|</span><br><span class="line">|<span class="string">              </span>|<span class="string">       </span>|<span class="string">   </span>|<span class="string">             Task     </span>|<span class="string">  </span>|<span class="string">              </span>|<span class="string">       </span>|</span><br><span class="line">|<span class="string">  ____________</span>|<span class="string">_____  </span>|<span class="string">   </span>|<span class="string">                      </span>|<span class="string">  </span>|<span class="string">  ____________</span>|<span class="string">_____  </span>|</span><br><span class="line">|<span class="string">  </span>|<span class="string">     </span>|<span class="string">     </span>|<span class="string">    </span>|<span class="string">  </span>|<span class="string">   </span>|<span class="string">                      </span>|<span class="string">  </span>|<span class="string">  </span>|<span class="string">     </span>|<span class="string">     </span>|<span class="string">    </span>|<span class="string">  </span>|</span><br><span class="line">|<span class="string"> ...   ...    </span>|<span class="string">   ... </span>|<span class="string">   </span>|<span class="string">                      </span>|<span class="string">  </span>|<span class="string"> ...   ...    </span>|<span class="string">   ... </span>|</span><br><span class="line">|<span class="string">           Django     </span>|<span class="string">   </span>|<span class="string">                      </span>|<span class="string">  </span>|<span class="string">           Django     </span>|</span><br><span class="line">|<span class="string">            WSGI      </span>|<span class="string">   </span>|<span class="string">                      </span>|<span class="string">  </span>|<span class="string">            WSGI      </span>|</span><br><span class="line"> ----------------------     ----------------------    ---------------------- </span><br><span class="line">           |<span class="string">                           </span>|<span class="string">                         </span>|</span><br><span class="line">           -------------------------------------------------------</span><br><span class="line">                      |<span class="string">                                </span>|</span><br><span class="line">               DB Box/Cluster                  Queue Box/cluster   </span><br><span class="line">             ----------------------          ---------------------- </span><br><span class="line">            |<span class="string">     Postgresql       </span>|<span class="string">        </span>|<span class="string">        Redis         </span>|</span><br><span class="line">            |<span class="string">                      </span>|<span class="string">        </span>|<span class="string">                      </span>|</span><br><span class="line">             ----------------------          ----------------------</span><br></pre></td></tr></table></figure><p>— END —</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;This is the architecture I designed for service “Managed Service for Alibaba Cloud” of company production. It’s also my common architecture that can be used to deploy distributed Python applications or service based on workers or MQ. This is a easy to upgrade architecture. You can simply add other service or make it becoming microservices.&lt;/p&gt;
    
    </summary>
    
      <category term="Architecture &amp; System" scheme="http://blog.samuelchen.net/categories/Architecture-System/"/>
    
    
      <category term="cloud" scheme="http://blog.samuelchen.net/tags/cloud/"/>
    
      <category term="deployment" scheme="http://blog.samuelchen.net/tags/deployment/"/>
    
      <category term="Python" scheme="http://blog.samuelchen.net/tags/Python/"/>
    
      <category term="Django" scheme="http://blog.samuelchen.net/tags/Django/"/>
    
      <category term="worker" scheme="http://blog.samuelchen.net/tags/worker/"/>
    
      <category term="PostgreSQL" scheme="http://blog.samuelchen.net/tags/PostgreSQL/"/>
    
      <category term="Alibaba Cloud" scheme="http://blog.samuelchen.net/tags/Alibaba-Cloud/"/>
    
      <category term="cluster" scheme="http://blog.samuelchen.net/tags/cluster/"/>
    
      <category term="CGI" scheme="http://blog.samuelchen.net/tags/CGI/"/>
    
      <category term="MQ" scheme="http://blog.samuelchen.net/tags/MQ/"/>
    
      <category term="database" scheme="http://blog.samuelchen.net/tags/database/"/>
    
      <category term="Redis" scheme="http://blog.samuelchen.net/tags/Redis/"/>
    
  </entry>
  
  <entry>
    <title>My Contributions to Open Source Projects</title>
    <link href="http://blog.samuelchen.net/my-contributions-to-open-source-projects/"/>
    <id>http://blog.samuelchen.net/my-contributions-to-open-source-projects/</id>
    <published>2020-06-11T13:40:03.000Z</published>
    <updated>2022-02-03T19:26:34.930Z</updated>
    
    <content type="html"><![CDATA[<p><em>整理了自己对开源软件做的一些修改、提交或者错误报告</em></p><a id="more"></a><ul><li><p>Alibaba Cloud SDK for Python</p><ul><li>support proxy environment var<br><a href="https://github.com/aliyun/aliyun-openapi-python-sdk/pull/72" target="_blank" rel="noopener">https://github.com/aliyun/aliyun-openapi-python-sdk/pull/72</a></li><li>review for commit DescribeFileSystemStatistics<br><a href="https://github.com/aliyun/aliyun-openapi-python-sdk/pull/315" target="_blank" rel="noopener">https://github.com/aliyun/aliyun-openapi-python-sdk/pull/315</a></li></ul></li><li><p>truepy - Python library for generating TrueLicense licenses</p><ul><li>Fix importing issue by replace “pycrypto” with “pycryptodome”<br><a href="https://github.com/moses-palmer/truepy/pull/5" target="_blank" rel="noopener">https://github.com/moses-palmer/truepy/pull/5</a></li></ul></li><li><p>Scrapy/w3lib - lib for html parsing in scrapy spider framework</p><ul><li>Report issue “Scrapy can not auto detect GBK html encoding” (work around in scrapy pipline/middleware way myself)<br><a href="https://github.com/scrapy/w3lib/issues/155" target="_blank" rel="noopener">https://github.com/scrapy/w3lib/issues/155</a></li></ul></li><li><p>Flask/Jinja - template engine for python</p><ul><li>Found &amp; report bug. “Traceback formatting in Python 3.6 32-bit Windows causes hang”<br><a href="https://github.com/pallets/jinja/issues/1162" target="_blank" rel="noopener">https://github.com/pallets/jinja/issues/1162</a></li></ul></li><li><p>Tonado - Python high performace web framework</p><ul><li>Fix broken demo<br><a href="https://github.com/tornadoweb/tornado/pull/1792" target="_blank" rel="noopener">https://github.com/tornadoweb/tornado/pull/1792</a></li></ul></li><li><p>KafkaOffsetMonitor - Montior tool for Kafaka</p><ul><li>Report bug about node on zookeeper cluster and figure out work around.<br><a href="https://github.com/quantifind/KafkaOffsetMonitor/issues/14" target="_blank" rel="noopener">https://github.com/quantifind/KafkaOffsetMonitor/issues/14</a></li></ul></li><li><p>fmdb - Object-C wrapper for SQLite</p><ul><li>Fix i myself reported bug (owner used his own fix). listed in contirbutors (line 36).<br><a href="https://github.com/ccgus/fmdb/pull/105" target="_blank" rel="noopener">https://github.com/ccgus/fmdb/pull/105</a><br><a href="https://github.com/ccgus/fmdb/blob/master/CONTRIBUTORS.txt" target="_blank" rel="noopener">https://github.com/ccgus/fmdb/blob/master/CONTRIBUTORS.txt</a></li></ul></li><li><p>TouchXml - iOS port of NSXMLDocument (XML parser)</p><ul><li>Add build target for framework<br><a href="https://github.com/TouchCode/TouchXML/pull/33" target="_blank" rel="noopener">https://github.com/TouchCode/TouchXML/pull/33</a></li></ul></li><li><p>Formalchemy - HTML form generation framework by Python</p><ul><li>fix to ignore the KeyError while sync data to model.<br><a href="https://github.com/FormAlchemy/formalchemy/pull/13" target="_blank" rel="noopener">https://github.com/FormAlchemy/formalchemy/pull/13</a></li><li>typo fix<br><a href="https://github.com/FormAlchemy/fa.jquery/pull/7" target="_blank" rel="noopener">https://github.com/FormAlchemy/fa.jquery/pull/7</a></li></ul></li></ul><p>— END —</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;em&gt;整理了自己对开源软件做的一些修改、提交或者错误报告&lt;/em&gt;&lt;/p&gt;
    
    </summary>
    
      <category term="Programming" scheme="http://blog.samuelchen.net/categories/Programming/"/>
    
    
      <category term="cloud" scheme="http://blog.samuelchen.net/tags/cloud/"/>
    
      <category term="Python" scheme="http://blog.samuelchen.net/tags/Python/"/>
    
      <category term="Alibaba Cloud" scheme="http://blog.samuelchen.net/tags/Alibaba-Cloud/"/>
    
      <category term="Scrapy" scheme="http://blog.samuelchen.net/tags/Scrapy/"/>
    
      <category term="Kafka" scheme="http://blog.samuelchen.net/tags/Kafka/"/>
    
      <category term="open source" scheme="http://blog.samuelchen.net/tags/open-source/"/>
    
      <category term="Flask" scheme="http://blog.samuelchen.net/tags/Flask/"/>
    
      <category term="Jinja" scheme="http://blog.samuelchen.net/tags/Jinja/"/>
    
      <category term="bug" scheme="http://blog.samuelchen.net/tags/bug/"/>
    
      <category term="Object-C" scheme="http://blog.samuelchen.net/tags/Object-C/"/>
    
      <category term="iOS" scheme="http://blog.samuelchen.net/tags/iOS/"/>
    
      <category term="truepy" scheme="http://blog.samuelchen.net/tags/truepy/"/>
    
      <category term="Tornado" scheme="http://blog.samuelchen.net/tags/Tornado/"/>
    
      <category term="fmdb" scheme="http://blog.samuelchen.net/tags/fmdb/"/>
    
      <category term="Zookeeper" scheme="http://blog.samuelchen.net/tags/Zookeeper/"/>
    
      <category term="touchxml" scheme="http://blog.samuelchen.net/tags/touchxml/"/>
    
      <category term="formalchemy" scheme="http://blog.samuelchen.net/tags/formalchemy/"/>
    
  </entry>
  
  <entry>
    <title>Window 批处理(BAT)中生成格式化日期时间字符串</title>
    <link href="http://blog.samuelchen.net/generate-date-time-string-in-window-bat/"/>
    <id>http://blog.samuelchen.net/generate-date-time-string-in-window-bat/</id>
    <published>2020-02-28T16:36:31.000Z</published>
    <updated>2022-02-03T19:26:34.930Z</updated>
    
    <content type="html"><![CDATA[<p>今天打算写一些脚本同时支持 Windows 和 Linux，因此需要同一个脚本需要写一个 shell 版本和一个 <code>bat</code> 版本。其中一项需求是要生成一个日志文件，文件后缀是当前系统时间的字符串’yyymmddMMHHSS’这种格式的，所以需要取到当前时间并格式化。在 Linux 中，这是一个很简单的需求，直接使用 <code>date +&#39;%y%m%d%H%M%S&#39;</code> 就可以拿到，但是在 Windows 中就非常麻烦了。</p><a id="more"></a><p>在 Windows 中，最直接的想法是和 Linux 类似，使用 <code>date /t</code> 和 <code>time /t</code> 命令来获取，然后利用<br><code>%date:~0,4%</code> 来取到年份（<code>%:~0,4%</code> 是 bat 取子字符串语法，表示取 0 到 4 个字符，前开后闭），<br>其他分别取到月、日、小时、分钟和秒，最后组合。完整的例子如下.</p><p><code>%date:~0,4%%date:~5,2%%date:~8,2%%time:~0,2%%time:~3,2%%time:~6,2%</code></p><p>这个例子<strong>基本上</strong>是可以工作的。但为什么说“基本上”？因为这个方法只能适用于部分系统，没有考虑区域(locale)。</p><p>由于 <code>Windows</code> 有区域和格式设定，所以 <code>date</code> 和 <code>time</code> 命令显示出来时间格式是经过格式化的，换<br>句话说，不同的区域由于设置的时间格式不同，返回的格式串就不同。比如中国/中文，经常使用 <code>2020-02-02</code><br>这种格式，而欧美/英文，经常使用 <code>02/02/20</code> 这种格式。所以上面那个在英文系统下，多半显示不对。</p><p>也在网上找了些例子，有些考虑到了不同的格式，但也是用 <code>date</code> 各种判断拼凑出来，也有提到<br>直接访问 CMOS 硬件 clock 的方法，都是非常麻烦，不太适用于写短小的<code>bat</code>批处理文件。</p><p>最终，找到了一个<strong>比较好</strong>的办法，那就是利用 <code>WMI</code> 的接口来直接获得时间。说说它比“比较好”的原因是<br>因为 <code>WMI</code> 的接口不一定每个机器都有，这个命令也是处于<code>deprecated</code>即将退休的状态。</p><figure class="highlight bat"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">@<span class="built_in">echo</span> off</span><br><span class="line"><span class="comment">rem set local ENABLEDELAYEDEXPANSION</span></span><br><span class="line"></span><br><span class="line">wmic /? &gt;&gt; <span class="built_in">nul</span>|| <span class="built_in">echo</span> "wmic <span class="keyword">not</span> found." &amp;&amp; <span class="built_in">echo</span> 'quit'</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> /f <span class="variable">%%i</span> <span class="keyword">in</span> ( 'wmic os get LocalDateTime /value' ) <span class="keyword">do</span> (</span><br><span class="line">    <span class="built_in">echo</span> "<span class="variable">%%i</span>" | <span class="built_in">findstr</span> "LocalDateTime" &gt; <span class="built_in">nul</span> &amp;&amp; <span class="built_in">set</span> DT=<span class="variable">%%i</span></span><br><span class="line">)</span><br><span class="line"><span class="built_in">set</span> DT=<span class="variable">%DT:~14,14%</span></span><br><span class="line"><span class="comment">rem echo "%DT%"</span></span><br></pre></td></tr></table></figure><p>此外，利用 <code>PowerShell</code> 也是一个<strong>比较好</strong>的办法，问题同样是可能有些机器没装。如果想处理时区信息，<br>可以使用 <code>tzinfo</code> 命令。</p><p>总之，根据自身需求和环境，选择合适的方法。</p><p>— END —</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;今天打算写一些脚本同时支持 Windows 和 Linux，因此需要同一个脚本需要写一个 shell 版本和一个 &lt;code&gt;bat&lt;/code&gt; 版本。其中一项需求是要生成一个日志文件，文件后缀是当前系统时间的字符串’yyymmddMMHHSS’这种格式的，所以需要取到当前时间并格式化。在 Linux 中，这是一个很简单的需求，直接使用 &lt;code&gt;date +&amp;#39;%y%m%d%H%M%S&amp;#39;&lt;/code&gt; 就可以拿到，但是在 Windows 中就非常麻烦了。&lt;/p&gt;
    
    </summary>
    
      <category term="Programming" scheme="http://blog.samuelchen.net/categories/Programming/"/>
    
    
      <category term="bat" scheme="http://blog.samuelchen.net/tags/bat/"/>
    
      <category term="Windows" scheme="http://blog.samuelchen.net/tags/Windows/"/>
    
      <category term="datetime" scheme="http://blog.samuelchen.net/tags/datetime/"/>
    
      <category term="string" scheme="http://blog.samuelchen.net/tags/string/"/>
    
  </entry>
  
  <entry>
    <title>Flask (Werkzeug) Templating Caused Trackback Loop Reference Issue</title>
    <link href="http://blog.samuelchen.net/flask-werkzeug-templating-caused-trackback-loop-issue/"/>
    <id>http://blog.samuelchen.net/flask-werkzeug-templating-caused-trackback-loop-issue/</id>
    <published>2020-02-28T08:24:15.000Z</published>
    <updated>2022-02-03T19:26:34.930Z</updated>
    
    <content type="html"><![CDATA[<pre><code>Found a Flask template bug caused by PyObject_HEAD size in Python for 32bit Windows. </code></pre><a id="more"></a><p>Today, I was facing an issue when using <code>Flask</code> template.</p><p>If use an dash “-“ linked variable name in Flask template, it will cause Flask to hang without<br>throwing any exception.</p><p>At beginning, I guess it may be an issue of <code>Jinja</code> template rending. But after traced in IDE<br>(Pycharm community 2019.3), I saw that templating raised the exception and <code>Werkzeug</code> is handling. </p><p>At first I uses Flask debug mode and IDE <strong>debug</strong> run to step into codes to dig it. IDE gets<br>slower and slower and the debugger hung in <code>Werkzerg</code> codes.</p><p>Eventually, I found an endless loop in <code>Python\Lib\traceback.py</code> to walk trackback stacks. The<br>trackbacks are stored in a link which nodes point to next. In <code>flask\templating.py</code>,<br><code>flask\app.py</code> and <code>werkzeug\debug\tbtools.py</code>, the exception was catched. In<br><code>handle_exception()</code> of <code>flask\app.py</code>, <code>Werkzeug</code> wants to log it and print it out.<br>The trackback link has looped reference as below picture.</p><p><img src="flask_tb_next_loop_ref.png" alt></p><p>Simple code to re-produce it as below (<strong>“font-size”</strong> variable caused.).</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> flask <span class="keyword">import</span> Flask, request, render_template_string, make_response, url_for, redirect</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">app = Flask(__name__)</span><br><span class="line"></span><br><span class="line">template_page = <span class="string">'''</span></span><br><span class="line"><span class="string">&lt;html&gt;</span></span><br><span class="line"><span class="string">&lt;head&gt;</span></span><br><span class="line"><span class="string">&lt;meta charset="&#123;&#123; encoding &#125;&#125;" /&gt;</span></span><br><span class="line"><span class="string">&lt;meta http-equiv="content-type" content="text/html; charset=&#123;&#123; encoding &#125;&#125;" /&gt;</span></span><br><span class="line"><span class="string">&lt;style type="text/css"&gt;</span></span><br><span class="line"><span class="string">  body, pre, p, div, input, h1,h2,h3,h4,h5 &#123;</span></span><br><span class="line"><span class="string">    font-family : Consolas, Courier New;</span></span><br><span class="line"><span class="string">  &#125;</span></span><br><span class="line"><span class="string">&lt;/style&gt;</span></span><br><span class="line"><span class="string">&lt;/head&gt;</span></span><br><span class="line"><span class="string">&lt;body&gt;</span></span><br><span class="line"><span class="string">    &lt;div id="wrapper" style="font-size:&#123;&#123; font-size &#125;&#125;em"&gt;</span></span><br><span class="line"><span class="string">        &#123;&#123; content | safe &#125;&#125;</span></span><br><span class="line"><span class="string">    &lt;/div&gt;</span></span><br><span class="line"><span class="string">&lt;/body&gt;'''</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">@app.route('/', methods=['GET'])</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">index</span><span class="params">()</span>:</span></span><br><span class="line">    context = &#123;</span><br><span class="line">        <span class="string">"encoding"</span>: <span class="string">'utf-8'</span>,</span><br><span class="line">        <span class="string">"font-size"</span>: <span class="number">0.9</span>,</span><br><span class="line">        <span class="string">"content"</span>: <span class="string">'hello flask'</span></span><br><span class="line">    &#125;</span><br><span class="line">    resp = make_response(render_template_string(template_page, **context))</span><br><span class="line">    resp.headers[<span class="string">'Content-Type'</span>] = <span class="string">'text/html; charset=utf-8'</span></span><br><span class="line">    <span class="keyword">return</span> resp</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">"__main__"</span>:</span><br><span class="line">    <span class="comment"># app.run(debug=True, host='0.0.0.0', port=8080)</span></span><br><span class="line"></span><br><span class="line">    app.run()</span><br></pre></td></tr></table></figure><p>Raised Github issue at <code>Flask</code>:</p><ul><li><a href="https://github.com/pallets/flask/issues/3516" target="_blank" rel="noopener">https://github.com/pallets/flask/issues/3516</a></li></ul><p>Environment:</p><ul><li>Window 10</li><li>Python 3.6.8150.1013 (venv)</li><li>Flask 1.1.1</li><li>Werkzeug 0.16.1</li></ul><p>Possible related Python issue:</p><ul><li><a href="https://bugs.python.org/issue9427" target="_blank" rel="noopener">Issue9427 - logging.error(‘…’, exc_info=True) should display upper frames, too</a></li><li><a href="https://bugs.python.org/issue1553375" target="_blank" rel="noopener">Issue1553375 - Add traceback.print_full_exception()</a></li></ul><p>— END —</p>]]></content>
    
    <summary type="html">
    
      &lt;pre&gt;&lt;code&gt;Found a Flask template bug caused by PyObject_HEAD size in Python for 32bit Windows. 
&lt;/code&gt;&lt;/pre&gt;
    
    </summary>
    
      <category term="Programming" scheme="http://blog.samuelchen.net/categories/Programming/"/>
    
    
      <category term="Python" scheme="http://blog.samuelchen.net/tags/Python/"/>
    
      <category term="template" scheme="http://blog.samuelchen.net/tags/template/"/>
    
      <category term="Flask" scheme="http://blog.samuelchen.net/tags/Flask/"/>
    
      <category term="Jinja" scheme="http://blog.samuelchen.net/tags/Jinja/"/>
    
      <category term="Werkzeug" scheme="http://blog.samuelchen.net/tags/Werkzeug/"/>
    
      <category term="bug" scheme="http://blog.samuelchen.net/tags/bug/"/>
    
      <category term="trackback" scheme="http://blog.samuelchen.net/tags/trackback/"/>
    
  </entry>
  
  <entry>
    <title>为 Hexo, Hugo 和 VSCode 添加 Markdown 流程图(Mermaid)支持</title>
    <link href="http://blog.samuelchen.net/Add-markdown-chart-to-VSCode-Hexo-and-Hugo/"/>
    <id>http://blog.samuelchen.net/Add-markdown-chart-to-VSCode-Hexo-and-Hugo/</id>
    <published>2020-02-06T07:54:51.000Z</published>
    <updated>2022-02-03T19:26:34.930Z</updated>
    
    <content type="html"><![CDATA[<p>最近在写blog时想画流程图，但又因为可能会频繁修改而不想用图片。因此经过一番搜寻，发现了 <a href="https://mermaid-js.github.io/mermaid/" target="_blank" rel="noopener"><code>mermaid</code></a><br>这个工具，支持用 <code>markdown</code> 撰写 <strong>流程图</strong>，<strong>时序图</strong>，<strong>甘特图</strong>，<strong>类图</strong> 等各种（简直神器）。<br>最让人高兴的是，Hexo（博客）, Hugo（网站） 以及 VSCode 都有插件或者方法可以支持。</p><a id="more"></a><p>以下就分别介绍如何在VSCode, Hexo 以及 Hugo 中安装设置来支持 <code>mermaid</code>.</p><h2 id="VSCode"><a href="#VSCode" class="headerlink" title="VSCode"></a>VSCode</h2><p>在 VSCode 中安装插件 <a href="https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid" target="_blank" rel="noopener"><code>Markdown Preview Mermaid Support</code></a>，<br>就可以在编辑时实时预览 <code>markdown</code> 中的 <code>mermaid</code> 图形了，图形编写使用 ``` 包围，并以 <code>mermaid</code>作为语言标签。</p><p>例如（：</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="code">` `</span> `mermaid</span><br><span class="line">graph TD;</span><br><span class="line"><span class="code">A--&gt;B;</span></span><br><span class="line"><span class="code">A--&gt;C;</span></span><br><span class="line"><span class="code">B--&gt;D;</span></span><br><span class="line"><span class="code">C--&gt;D;</span></span><br><span class="line"><span class="code">` `</span> `</span><br></pre></td></tr></table></figure><p>如图所示：<br><img src="vscode-markdown-flowchart.png" alt></p><h2 id="Hexo"><a href="#Hexo" class="headerlink" title="Hexo"></a>Hexo</h2><p>Hexo 默认是不支持 <code>mermaid</code> 的，需要添加插件支持，在你的 Hexo Blog 目录下，输入命令：</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install --save hexo-filter-mermaid-diagrams</span><br></pre></td></tr></table></figure><p>此外，如果使用的主题支持<code>mermaid</code>，需要在所用主题的 <code>_config.yml</code> 中开启 <code>mermaid</code> 支持：</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Mermaid (markdwon to flow chart, seq chart, class chart ...)</span></span><br><span class="line"><span class="attr">mermaid:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="comment"># Available themes: default | dark | forest | neutral</span></span><br><span class="line">  <span class="attr">theme:</span> <span class="string">default</span></span><br></pre></td></tr></table></figure><pre><code>*请稍等一段时间，以下代码会变为SVG流程图*</code></pre><pre class="mermaid">graph TD;    A-->B;    A-->C;    B-->D;    C-->D;</pre><p><strong>如果所使用的主题不支持 <code>mermaid</code>，请参考 <a href></a></strong></p><h3 id="给-Hexo-主题添加-memaid-支持"><a href="#给-Hexo-主题添加-memaid-支持" class="headerlink" title="给 Hexo 主题添加 memaid 支持"></a>给 Hexo 主题添加 <code>memaid</code> 支持</h3><p>最简单的办法，利用<code>mermaid</code>官方CDN，直接在 ${blog}\themes\tranquilpeak\layout_partial\script.ejs<br>中修改，文件最后增加两行如下</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&lt;script src=<span class="string">"https://unpkg.com/mermaid@8.4.6/dist/mermaid.min.js"</span>&gt;&lt;<span class="regexp">/script&gt;</span></span><br><span class="line"><span class="regexp">&lt;script&gt;mermaid.initialize(&#123;startOnLoad:true&#125;);&lt;/</span>script&gt;</span><br></pre></td></tr></table></figure><p>如果希望这个主题能支持更多配置，可以在主题的 <code>_config.yml</code> 中增加 <code>mermaid</code> 配置：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Mermaid (markdwon to flow chart, seq chart, class chart ...)</span></span><br><span class="line"><span class="attr">mermaid:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="comment"># Available themes: default | dark | forest | neutral</span></span><br><span class="line">  <span class="attr">theme:</span> <span class="string">default</span></span><br><span class="line">  <span class="comment"># You can add more options</span></span><br></pre></td></tr></table></figure><p>然后在 <code>${blog}\themes\tranquilpeak\layout\_partial\script.ejs</code> 中修改，文件最后增加：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">&lt;% <span class="keyword">if</span> (theme.mermaid.enable) &#123; %&gt;</span><br><span class="line">    &lt;%- js(<span class="string">'assets/js/mermaid.min.js'</span>) %&gt;</span><br><span class="line">    &lt;script&gt;</span><br><span class="line">        $(<span class="built_in">document</span>).ready(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">            <span class="keyword">var</span> mermaid_config = &#123;</span><br><span class="line">                startOnLoad: <span class="literal">true</span>,</span><br><span class="line">                theme: <span class="string">'&lt;%- theme.mermaid.theme %&gt;'</span>,</span><br><span class="line">                flowchart:&#123;</span><br><span class="line">                    useMaxWidth: <span class="literal">false</span>,</span><br><span class="line">                    htmlLabels: <span class="literal">true</span></span><br><span class="line">                &#125;                </span><br><span class="line">            &#125;</span><br><span class="line">            mermaid.initialize(mermaid_config);</span><br><span class="line">        &#125;);</span><br><span class="line">    &lt;<span class="regexp">/script&gt;</span></span><br><span class="line"><span class="regexp">&lt;% &#125; %&gt;</span></span><br></pre></td></tr></table></figure><p>其中 <code>theme.mermaid.enable</code> <code>theme.mermaid.theme</code> 就是你增加的主题配置选项，具体<br>详见 <code>mermaid</code> 官方文档。</p><p>最后，可以将 <code>mermaid.min.js</code> 放到主题的js目录 <code>${blog}\themes\tranquilpeak\source\assets\js\</code> 下，<br>再使用如下技巧，当 CDN 出问题时，可以使用本地文件。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;!-- <span class="keyword">if</span> CDN fails, use local file --&gt;</span><br><span class="line">&lt;script src=<span class="string">"https://unpkg.com/mermaid@8.4.6/dist/mermaid.min.js"</span>&gt;&lt;<span class="regexp">/script&gt;</span></span><br><span class="line"><span class="regexp">&lt;script&gt; window.mermaid || document.write('&lt;script src="/</span>assets/js/mermaid.min.js<span class="string">"&gt;&lt;\/script&gt;')&lt;/script&gt;</span></span><br></pre></td></tr></table></figure><h2 id="Hugo"><a href="#Hugo" class="headerlink" title="Hugo"></a>Hugo</h2><pre><code>to be written理论上和 Hexo 类似，待写</code></pre><p>— END —</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;最近在写blog时想画流程图，但又因为可能会频繁修改而不想用图片。因此经过一番搜寻，发现了 &lt;a href=&quot;https://mermaid-js.github.io/mermaid/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;mermaid&lt;/code&gt;&lt;/a&gt;&lt;br&gt;这个工具，支持用 &lt;code&gt;markdown&lt;/code&gt; 撰写 &lt;strong&gt;流程图&lt;/strong&gt;，&lt;strong&gt;时序图&lt;/strong&gt;，&lt;strong&gt;甘特图&lt;/strong&gt;，&lt;strong&gt;类图&lt;/strong&gt; 等各种（简直神器）。&lt;br&gt;最让人高兴的是，Hexo（博客）, Hugo（网站） 以及 VSCode 都有插件或者方法可以支持。&lt;/p&gt;
    
    </summary>
    
      <category term="Utility" scheme="http://blog.samuelchen.net/categories/Utility/"/>
    
    
      <category term="Hexo" scheme="http://blog.samuelchen.net/tags/Hexo/"/>
    
      <category term="blog" scheme="http://blog.samuelchen.net/tags/blog/"/>
    
      <category term="diagram" scheme="http://blog.samuelchen.net/tags/diagram/"/>
    
      <category term="flowchart" scheme="http://blog.samuelchen.net/tags/flowchart/"/>
    
      <category term="Mermaid" scheme="http://blog.samuelchen.net/tags/Mermaid/"/>
    
      <category term="markdown" scheme="http://blog.samuelchen.net/tags/markdown/"/>
    
      <category term="Hugo" scheme="http://blog.samuelchen.net/tags/Hugo/"/>
    
      <category term="VSCode" scheme="http://blog.samuelchen.net/tags/VSCode/"/>
    
  </entry>
  
  <entry>
    <title>使用 Rclone 同步云端和本地文件以部署静态网站</title>
    <link href="http://blog.samuelchen.net/Use-rclone-to-sync-your-files-with-cloud/"/>
    <id>http://blog.samuelchen.net/Use-rclone-to-sync-your-files-with-cloud/</id>
    <published>2019-05-05T07:11:18.000Z</published>
    <updated>2022-02-03T19:26:34.930Z</updated>
    
    <content type="html"><![CDATA[<p>之前在<a href="/Deploy-Hexo-static-website-on-Azure-Blob-storage/">这篇blog</a>中介绍过使用Azure Client <code>az</code> 来部署生成到网站. 使用<code>az</code>很方便，但是也有些缺点，例如会把整个网站全部重新上传一遍，速度慢不说，还浪费多次<code>blob</code>的操作。后来找到了另外一个工具<code>rclone</code>（<a href="https://rclone.org" target="_blank" rel="noopener">下载、安装、文档</a>，或使用各平台包管理器安装），它可以像<code>rsync</code>一样同步本地和远端文件，只更新变化过的文件。</p><a id="more"></a><p>使用起来也很简单， 首先新建一个远端配置<code>rclone config</code>，根据提示，输入名字，类型，account 或者 connection string。例如，我配置 <code>azure-chen</code> 这个名字（本地名称）对应 azure 上 <code>chen</code> 这个 blob 账号。然后就可以使用了：</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 列出远端容器</span></span><br><span class="line">rclone lsd azure-chen:</span><br><span class="line"></span><br><span class="line">          -1 2019-04-12 13:09:50        -1 <span class="variable">$web</span></span><br><span class="line">  </span><br><span class="line"><span class="comment"># 列出容器中文件</span></span><br><span class="line">rclone ls azure-chen:\<span class="variable">$web</span></span><br><span class="line"></span><br><span class="line">    11965 404.html</span><br><span class="line">...</span><br><span class="line">...</span><br><span class="line">    42150 all-tags/index.html</span><br><span class="line">    12676 archives/2011/03/index.html</span><br><span class="line">    12150 archives/2011/04/index.html</span><br><span class="line">    10677 archives/2011/06/index.html</span><br><span class="line">    17724 archives/2011/index.html</span><br><span class="line">    10626 archives/2012/03/index.html</span><br><span class="line">    10316 archives/2012/06/index.html</span><br><span class="line">    12050 archives/2012/index.html</span><br><span class="line">    10429 archives/2014/04/index.html</span><br><span class="line">    10424 archives/2014/index.html</span><br><span class="line">    10545 archives/2017/12/index.html</span><br><span class="line">    10539 archives/2017/index.html</span><br><span class="line">    10792 archives/2018/11/index.html</span><br><span class="line">    10786 archives/2018/index.html</span><br><span class="line">    10715 archives/2019/04/index.html</span><br><span class="line">    10710 archives/2019/index.html</span><br><span class="line">    26245 archives/index.html</span><br><span class="line">    10983 archives/page/2/index.html</span><br><span class="line">    28747 assets/css/font-awesome.css</span><br><span class="line">      735 assets/css/jquery.fancybox-thumbs.css</span><br><span class="line">     4955 assets/css/jquery.fancybox.css</span><br><span class="line">    93008 assets/css/style.css</span><br><span class="line">    74762 assets/css/style.min.css</span><br><span class="line">    58575 assets/css/tranquilpeak.css</span><br><span class="line">    93888 assets/fonts/FontAwesome.otf</span><br><span class="line">    60767 assets/fonts/fontawesome-webfont.eot</span><br><span class="line">   313398 assets/fonts/fontawesome-webfont.svg</span><br><span class="line">   122092 assets/fonts/fontawesome-webfont.ttf</span><br><span class="line">    71508 assets/fonts/fontawesome-webfont.woff</span><br><span class="line">    56780 assets/fonts/fontawesome-webfont.woff2</span><br><span class="line">    31124 assets/fonts/merriweather-bold.ttf</span><br><span class="line">    24668 assets/fonts/merriweather-boldItalic.ttf</span><br><span class="line">    31304 assets/fonts/merriweather-light.ttf</span><br><span class="line">    22264 assets/fonts/merriweather-lightItalic.ttf</span><br><span class="line">    30972 assets/fonts/merriweather.ttf</span><br><span class="line">    24476 assets/fonts/open-sans-bold.ttf</span><br><span class="line">    24292 assets/fonts/open-sans.ttf</span><br><span class="line">   143844 assets/images/avatar.gif</span><br><span class="line">       43 assets/images/blank.gif</span><br><span class="line">   259098 assets/images/cover.jpg</span><br><span class="line">     6567 assets/images/fancybox_loading.gif</span><br><span class="line">    13984 assets/images/fancybox_loading@2x.gif</span><br><span class="line">     1003 assets/images/fancybox_overlay.png</span><br><span class="line">     1362 assets/images/fancybox_sprite.png</span><br><span class="line">     6553 assets/images/fancybox_sprite@2x.png</span><br><span class="line">...</span><br><span class="line">...</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查</span></span><br><span class="line">rclone check ./public azure-chen:\<span class="variable">$web</span></span><br><span class="line"></span><br><span class="line">2019/05/05 14:49:44 ERROR : ... : File not <span class="keyword">in</span> Local file system at /path/to/<span class="built_in">local</span>/files/work/my-blog/public</span><br><span class="line">2019/05/05 14:49:44 ERROR : tags/Article/index.html: File not <span class="keyword">in</span> Local file system at /path/to/<span class="built_in">local</span>/files/work/my-blog/public</span><br><span class="line">2019/05/05 14:49:44 ERROR : tags/Config/index.html: File not <span class="keyword">in</span> Local file system at /path/to/<span class="built_in">local</span>/files/work/my-blog/public</span><br><span class="line">2019/05/05 14:49:44 ERROR : tags/Encoding/index.html: File not <span class="keyword">in</span> Local file system at /path/to/<span class="built_in">local</span>/files/work/my-blog/public</span><br><span class="line">2019/05/05 14:49:44 ERROR : tags/Mac/index.html: File not <span class="keyword">in</span> Local file system at /path/to/<span class="built_in">local</span>/files/work/my-blog/public</span><br><span class="line">2019/05/05 14:49:44 ERROR : tags/Network/index.html: File not <span class="keyword">in</span> Local file system at /path/to/<span class="built_in">local</span>/files/work/my-blog/public</span><br><span class="line">2019/05/05 14:49:44 ERROR : tags/Monitor/index.html: File not <span class="keyword">in</span> Local file system at /path/to/<span class="built_in">local</span>/files/work/my-blog/public</span><br><span class="line">2019/05/05 14:49:44 ERROR : tags/Programming/index.html: File not <span class="keyword">in</span> Local file system at /path/to/<span class="built_in">local</span>/files/work/my-blog/public</span><br><span class="line">2019/05/05 14:49:44 ERROR : tags/Static/index.html: File not <span class="keyword">in</span> Local file system at /path/to/<span class="built_in">local</span>/files/work/my-blog/public</span><br><span class="line">2019/05/05 14:49:44 ERROR : tags/Template/index.html: File not <span class="keyword">in</span> Local file system at /path/to/<span class="built_in">local</span>/files/work/my-blog/public</span><br><span class="line">2019/05/05 14:49:44 NOTICE: Local file system at /path/to/<span class="built_in">local</span>/files/work/my-blog/public: 10 files missing</span><br><span class="line">2019/05/05 14:49:44 NOTICE: Azure container <span class="variable">$web</span>: 10 differences found</span><br><span class="line">2019/05/05 14:49:44 NOTICE: Azure container <span class="variable">$web</span>: 111 matching files</span><br><span class="line">2019/05/05 14:49:44 Failed to check: 10 differences found</span><br><span class="line"><span class="comment"># 发现 10 个不同</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 同步 （从本地到远端）</span></span><br><span class="line">rclone sync ./public azure-chen:\<span class="variable">$web</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 再次 check</span></span><br><span class="line">rclone check ./public/ blog:\<span class="variable">$web</span></span><br><span class="line"></span><br><span class="line">2019/05/05 14:51:17 NOTICE: Azure container <span class="variable">$web</span>: 0 differences found</span><br><span class="line">2019/05/05 14:51:17 NOTICE: Azure container <span class="variable">$web</span>: 111 matching files</span><br><span class="line"><span class="comment"># 没有不同到了（远端到已经被删除）</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 编辑一个网页并重新生成网站</span></span><br><span class="line">hexo gen</span><br><span class="line"></span><br><span class="line"><span class="comment"># 再次 check</span></span><br><span class="line">rclone check ./public/ blog:\<span class="variable">$web</span></span><br><span class="line"></span><br><span class="line">2019/05/05 14:55:32 ERROR : atom.xml: Sizes differ</span><br><span class="line">2019/05/05 14:55:32 ERROR : index.html: Sizes differ</span><br><span class="line">2019/05/05 14:55:32 ERROR : sitemap.xml: MD5 differ</span><br><span class="line">2019/05/05 14:55:32 ERROR : Deploy-Hexo-static-website-on-Azure-Blob-storage/index.html: Sizes differ</span><br><span class="line">2019/05/05 14:55:32 ERROR : archives/index.html: Sizes differ</span><br><span class="line">2019/05/05 14:55:32 ERROR : all-categories/index.html: MD5 differ</span><br><span class="line">2019/05/05 14:55:32 ERROR : all-tags/index.html: MD5 differ</span><br><span class="line">2019/05/05 14:55:32 ERROR : categories/Cloud2End/index.html: Sizes differ</span><br><span class="line">2019/05/05 14:55:32 ERROR : archives/2019/index.html: Sizes differ</span><br><span class="line">2019/05/05 14:55:32 ERROR : tags/Hexo/index.html: Sizes differ</span><br><span class="line">2019/05/05 14:55:32 ERROR : archives/2019/04/index.html: Sizes differ</span><br><span class="line">2019/05/05 14:55:32 ERROR : tags/Azure/index.html: Sizes differ</span><br><span class="line">2019/05/05 14:55:33 ERROR : tags/blob/index.html: Sizes differ</span><br><span class="line">2019/05/05 14:55:33 ERROR : tags/deployment/index.html: Sizes differ</span><br><span class="line">2019/05/05 14:55:33 ERROR : tags/static/index.html: Sizes differ</span><br><span class="line">2019/05/05 14:55:33 NOTICE: Azure container <span class="variable">$web</span>: 15 differences found</span><br><span class="line">2019/05/05 14:55:33 NOTICE: Azure container <span class="variable">$web</span>: 96 matching files</span><br><span class="line">2019/05/05 14:55:33 Failed to check: 15 differences found</span><br><span class="line"><span class="comment"># 发现15处不同</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 部署（同步）</span></span><br><span class="line">rclone sync ./public azure-chen:\<span class="variable">$web</span></span><br></pre></td></tr></table></figure><p>这样，就可以把远端有，而本地没有到删除，而本地新增到也会复制到远端，减少了很多IO。</p><p>另外，还有两个GUI工具(for macOS)：</p><ul><li>Rclone OSX - <a href="https://github.com/rsyncOSX/rcloneosx" target="_blank" rel="noopener">https://github.com/rsyncOSX/rcloneosx</a></li><li>Rclone Browser - <a href="https://github.com/mmozeiko/RcloneBrowser" target="_blank" rel="noopener">https://github.com/mmozeiko/RcloneBrowser</a></li></ul><p>Rclone Browser 略微有点小问题， 并至今有2年没更新了，需要自己查issues<a href="https://github.com/mmozeiko/RcloneBrowser/issues/136" target="_blank" rel="noopener">解决</a>。</p><p>— END —</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;之前在&lt;a href=&quot;/Deploy-Hexo-static-website-on-Azure-Blob-storage/&quot;&gt;这篇blog&lt;/a&gt;中介绍过使用Azure Client &lt;code&gt;az&lt;/code&gt; 来部署生成到网站. 使用&lt;code&gt;az&lt;/code&gt;很方便，但是也有些缺点，例如会把整个网站全部重新上传一遍，速度慢不说，还浪费多次&lt;code&gt;blob&lt;/code&gt;的操作。后来找到了另外一个工具&lt;code&gt;rclone&lt;/code&gt;（&lt;a href=&quot;https://rclone.org&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;下载、安装、文档&lt;/a&gt;，或使用各平台包管理器安装），它可以像&lt;code&gt;rsync&lt;/code&gt;一样同步本地和远端文件，只更新变化过的文件。&lt;/p&gt;
    
    </summary>
    
      <category term="Architecture &amp; System" scheme="http://blog.samuelchen.net/categories/Architecture-System/"/>
    
    
      <category term="cloud" scheme="http://blog.samuelchen.net/tags/cloud/"/>
    
      <category term="deployment" scheme="http://blog.samuelchen.net/tags/deployment/"/>
    
      <category term="static" scheme="http://blog.samuelchen.net/tags/static/"/>
    
      <category term="Azure" scheme="http://blog.samuelchen.net/tags/Azure/"/>
    
      <category term="blob" scheme="http://blog.samuelchen.net/tags/blob/"/>
    
      <category term="rsync" scheme="http://blog.samuelchen.net/tags/rsync/"/>
    
      <category term="synchronization" scheme="http://blog.samuelchen.net/tags/synchronization/"/>
    
  </entry>
  
  <entry>
    <title>在 Azure Blob 存储上部署 Hexo 静态网站</title>
    <link href="http://blog.samuelchen.net/Deploy-Hexo-static-website-on-Azure-Blob-storage/"/>
    <id>http://blog.samuelchen.net/Deploy-Hexo-static-website-on-Azure-Blob-storage/</id>
    <published>2019-04-16T16:10:39.000Z</published>
    <updated>2022-02-03T19:26:34.930Z</updated>
    
    <content type="html"><![CDATA[<pre><code>_所有静态网站都可用采用此方法_</code></pre><p>之前，<a href="http://blog.samuelchen.net">个人博客</a>一直都是用 <code>Hexo</code> 生成并部署为 <code>GitHub Pages</code>。<br>最近知道，因为百度的爬虫太频繁而被 GitHub 屏蔽了，所以所有部署在 GitHub 上的网站都没有收录。<br>不深究这个理由是否靠谱，得给博客换个地方了。</p><p>手头有 Azure 和 Vultr 的 VPS，但考虑到部署静态网站到 VPS 有点大材小用，而且需要部署 HTTP<br>Server 防火墙，FTP/Rsync/SSH 等等挺麻烦，就寻思着是不是能用对象存储来做。于是翻看了 Azure<br>Blob 到文档，发现真还行，而且还挺简单，内置支持。</p><p>首先新建<strong>全局唯一</strong>的存储账号，比如我选则了 <code>chen</code>，这个会作为你 Azure 存储的一个 End<br>Point，比如 chen.blob.core.windows.net，可以直接通过这个域名来访问你的存储对象。这个时候<br>要注意一点，一定要选择 <code>StorageV2 (通用版 v2)</code> 类型，只有这个类型才支持直接部署静态网站。<br>我之前就是选择了 <code>v1</code> 类型，导致无法自动识别 <code>index.html</code> 而无法访问。建好后，选择<br><code>静态网站</code> 菜单并 <strong>启用</strong>，系统会自动生成名为 <code>$web</code> 的 <code>容器(Container)</code>，作为存储网站的根目录。</p><p>以上配置完成后，就用 <code>hexo generate</code> 命令生成你的网站，网站生成后都在 <code>public</code> 目录<br>下，这些不细说。然后需要做的是把生成的网站传到刚建立到容器 <code>blog</code> 中，有几种方法可以做到：</p><ol><li>直接使用浏览器在 Azure 门户页面 <code>存储资源管理器</code> 中上传</li><li>下载 <code>存储资源管理器</code> 桌面版，上传</li><li>使用 <code>AzCopy</code> 上传 （需要.net）</li><li>使用 Azure Client 命令行工具 <code>az</code></li></ol><p>前面2种方法都很简单，找到相应位置或者下载软件就行了，第3个需要.net，不足够通用，我使用到是第4种<br>方法，简单写了个脚本，每次自动上传，主要是下面这句，其他都省略了:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/usr/bin/env sh</span></span><br><span class="line"></span><br><span class="line">BLOB_ACCOUNT=<span class="string">"chen"</span>     <span class="comment"># blob 账号</span></span><br><span class="line">BLOB_CONTAINER=<span class="string">'$web'</span>   <span class="comment"># blob 容器</span></span><br><span class="line"></span><br><span class="line">hexo clean &amp;&amp; hexo generate &amp;&amp; az storage blob upload-batch -d <span class="variable">$BLOB_CONTAINER</span> --account-name <span class="variable">$BLOB_ACCOUNT</span> -s ./public</span><br></pre></td></tr></table></figure><p>然后就可以用 <code>https://chen.z?.web.core.windows.net</code> (？是某个数字，z? 代表一个地区)<br>访问你的网站了。</p><p>安装 Azure Client 的步骤就不写了，直接看文档。安装好后，记得运行 <code>az login</code> 登录。</p><p>最后，如果你有自己的域名，可以选择 <code>自定义域</code> 来配置，同时要配置 DNS.</p><p>这种方法非常简单，费用也很低，基础 1G 才大概几美分。不过有一点不好的是，<code>v2</code> 类型的 blob 存储<br>还有存取访问计费，每万次也有几～几十美分，而 Hexo 生成的静态网站文件很多，一次上传就得几百上千<br>个文件，而且只要改配置或者模版，文件就都大多数都修改了，得全部上传。</p><p>Azure Blob 部署的静态网站，如果用 <code>windows.net</code> 访问，是自带 <code>https</code> 的，如果你需要给<br>自定义域名也用上https，需要配置 <code>CDN</code>。而且，<code>CDN</code> 会自动选择不同的地区访问，blob 是固定<br>地区的（比如 blob 账号、容器是在 美国东部 US-EAST，那么亚洲访问就稍慢）。</p><p>— END —</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;pre&gt;&lt;code&gt;_所有静态网站都可用采用此方法_
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;之前，&lt;a href=&quot;http://blog.samuelchen.net&quot;&gt;个人博客&lt;/a&gt;一直都是用 &lt;code&gt;Hexo&lt;/code&gt; 生成并部署为 &lt;code&gt;GitHub Page
      
    
    </summary>
    
      <category term="Architecture &amp; System" scheme="http://blog.samuelchen.net/categories/Architecture-System/"/>
    
    
      <category term="cloud" scheme="http://blog.samuelchen.net/tags/cloud/"/>
    
      <category term="deployment" scheme="http://blog.samuelchen.net/tags/deployment/"/>
    
      <category term="static" scheme="http://blog.samuelchen.net/tags/static/"/>
    
      <category term="Azure" scheme="http://blog.samuelchen.net/tags/Azure/"/>
    
      <category term="Hexo" scheme="http://blog.samuelchen.net/tags/Hexo/"/>
    
      <category term="blob" scheme="http://blog.samuelchen.net/tags/blob/"/>
    
  </entry>
  
  <entry>
    <title>基于 HashiCorp Vault 和 Consul 的密钥仓库解决方案</title>
    <link href="http://blog.samuelchen.net/keystore-ha-solution-by-vault-consul/"/>
    <id>http://blog.samuelchen.net/keystore-ha-solution-by-vault-consul/</id>
    <published>2019-03-26T20:49:12.000Z</published>
    <updated>2020-06-16T15:14:03.000Z</updated>
    
    <content type="html"><![CDATA[<p>Keystore cluster based on Vault &amp; Consul</p><p>具体部署可参考 <a href="../encrypt-decrypt-and-store-sensitive-content-with-hashicorp-vault">敏感信息的加密存储</a> 以及 <a href="../service-discover-by-donsul">基于 Consul 的服务发现</a></p><a id="more"></a><p>Vault + consul 配置</p><p>Consul 配置. consul1.json: :</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">"datacenter"</span>: <span class="string">"cn-shanghai-b"</span>,</span><br><span class="line">  <span class="attr">"data_dir"</span>: <span class="string">"./consul"</span>,</span><br><span class="line">  <span class="attr">"log_level"</span>: <span class="string">"INFO"</span>,</span><br><span class="line">  <span class="attr">"node_name"</span>: <span class="string">"consul1"</span>,</span><br><span class="line">  <span class="attr">"server"</span>: <span class="literal">true</span>,</span><br><span class="line">  <span class="attr">"bootstrap_expect"</span>: <span class="number">3</span>,</span><br><span class="line">  <span class="attr">"rejoin_after_leave"</span>: <span class="literal">true</span>,</span><br><span class="line">  <span class="attr">"disable_host_node_id"</span>: <span class="literal">true</span>,</span><br><span class="line">  <span class="attr">"retry_join"</span>: [<span class="string">"vault2"</span>, <span class="string">"vault3"</span>],</span><br><span class="line">  <span class="attr">"ui"</span>: <span class="literal">true</span>,</span><br><span class="line">  <span class="attr">"bind_addr"</span>: <span class="string">"172.16.2.240"</span>,</span><br><span class="line">  <span class="attr">"addresses"</span>: &#123;</span><br><span class="line">    <span class="attr">"http"</span>: <span class="string">"0.0.0.0"</span></span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">"ports"</span>: &#123;</span><br><span class="line">  &#125;</span><br><span class="line">  ,</span><br><span class="line">  <span class="attr">"services"</span>: [</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="attr">"name"</span>: <span class="string">"vault"</span>,</span><br><span class="line">        <span class="attr">"port"</span>: <span class="number">8200</span>,</span><br><span class="line">        <span class="attr">"check"</span>: &#123;</span><br><span class="line">          <span class="attr">"id"</span>: <span class="string">"vault1"</span>,</span><br><span class="line">          <span class="attr">"http"</span>: <span class="string">"http://vault1:8200"</span>,</span><br><span class="line">          <span class="attr">"tls_skip_verify"</span>: <span class="literal">true</span>,</span><br><span class="line">          <span class="attr">"interval"</span>: <span class="string">"10s"</span>,</span><br><span class="line">          <span class="attr">"timeout"</span>: <span class="string">"3s"</span>,</span><br><span class="line">          <span class="attr">"status"</span>: <span class="string">"passing"</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Vault 配置. vault.hcl:</p><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">storage <span class="string">"consul"</span> &#123;</span><br><span class="line"> <span class="built_in"> address </span>= <span class="string">"127.0.0.1:8500"</span></span><br><span class="line">  path    = <span class="string">"vault"</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">listener <span class="string">"tcp"</span> &#123;</span><br><span class="line"> <span class="built_in"> address </span>    = <span class="string">"0.0.0.0:8200"</span></span><br><span class="line">  tls_disable = 1</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">disable_mlock = 1</span><br><span class="line">api_addr = <span class="string">"http://vault:8200"</span></span><br><span class="line">ui = <span class="literal">true</span></span><br></pre></td></tr></table></figure><p>— END —</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Keystore cluster based on Vault &amp;amp; Consul&lt;/p&gt;
&lt;p&gt;具体部署可参考 &lt;a href=&quot;../encrypt-decrypt-and-store-sensitive-content-with-hashicorp-vault&quot;&gt;敏感信息的加密存储&lt;/a&gt; 以及 &lt;a href=&quot;../service-discover-by-donsul&quot;&gt;基于 Consul 的服务发现&lt;/a&gt;&lt;/p&gt;
    
    </summary>
    
      <category term="Architecture &amp; System" scheme="http://blog.samuelchen.net/categories/Architecture-System/"/>
    
    
      <category term="cloud" scheme="http://blog.samuelchen.net/tags/cloud/"/>
    
      <category term="deployment" scheme="http://blog.samuelchen.net/tags/deployment/"/>
    
      <category term="Consul" scheme="http://blog.samuelchen.net/tags/Consul/"/>
    
      <category term="HashiCorp" scheme="http://blog.samuelchen.net/tags/HashiCorp/"/>
    
      <category term="Vault" scheme="http://blog.samuelchen.net/tags/Vault/"/>
    
      <category term="keystore" scheme="http://blog.samuelchen.net/tags/keystore/"/>
    
      <category term="cluster" scheme="http://blog.samuelchen.net/tags/cluster/"/>
    
  </entry>
  
  <entry>
    <title>Encrypt/Decrypt and Store Sensitive Content With HashiCorp Vault</title>
    <link href="http://blog.samuelchen.net/encrypt-decrypt-and-store-sensitive-content-with-hashicorp-vault/"/>
    <id>http://blog.samuelchen.net/encrypt-decrypt-and-store-sensitive-content-with-hashicorp-vault/</id>
    <published>2019-02-27T04:12:39.000Z</published>
    <updated>2020-06-15T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<p>We are encrypting sensitive content with AES algorithm and storing them in DB. Now we plan to leverage HashiCorp Vault to do this.</p><a id="more"></a><p>So far we have 2 kinds of data need to be encrypted: one is the Alicloud key and secret of customers, the other is the marked sensitive variable or parameters such as VM password. Vault provides several secrets engines to achieve these.</p><p>Vault has a secret engine named  AliCloud. But it can only manage one account with configuring a pair of its key and secret in a single path. It can only manage the policies of this account. Which means if we want store multiple customer AliCloud accounts, we need to define multiple paths in Vault for each account and configure key/secret pairs for each account manually. It’s no sense. So it’s not useful for us.</p><p>Above all, we could only use the <code>Key/Value</code> secrets engine. </p><h3 id="Configuration"><a href="#Configuration" class="headerlink" title="Configuration"></a>Configuration</h3><p>We define some configurations for using Vault.</p><ul><li><p><code>ENCRYPTION_METHOD</code>  -  to identify which method will be used. <code>VAULT</code>for HashiCorp vault. <code>AES</code>for encryption with AES algorithm and store in DB.  <code>ENCRYPTION_METHOD  = “VAULT” | “AES”</code></p></li><li><p><code>VAULT_KV_PATH</code> - Vault path is related to secrets engine. This need to defined from architecture level so that all components which uses Vault will follow it. And avoid namespace conflict. By default, the base path for <code>Key/Value</code> engine is <code>“kv”</code>. e.g. <code>VAULT_KV_PATH = “kv/cpsapi”</code></p></li></ul><h3 id="NOTABLE-IMPLEMENTATION-details"><a href="#NOTABLE-IMPLEMENTATION-details" class="headerlink" title="NOTABLE IMPLEMENTATION details"></a>NOTABLE IMPLEMENTATION details</h3><ul><li>To distinguish encryption methods for the encrypted data, we add prefix for it. e.g.  for AES, it will be <code>“**$:AES:$**qowzobv1GoC8tB7dOrHJpA==PXyKO2kLX6C4oD8a+e5BlMQwD2q8vvu3poI5rishmVM=”</code> . If data encrypted by Vault, the encrypted data will not be stored in DB. So that it will only remains <code>“$:VAULT:$”</code> </li><li>Two utility methods wrapper <code>encrypt/decrypt</code> were created. In them, we automatically check which methods will be used and apply it. If the <code>ENCRYPTION_METHODS</code> was changed after the system runs for some while, we may be facing some data was encrypted by AES but now the decryption method is VAULT. For this scenario, we have 2 choices:<ul><li>Decrypt the data as it was. Encrypt it as configured.</li><li>Raise an exception to notify. This means if a encryption methods is used when the system initializing, it can not be changed.</li></ul></li><li>Data length changed. Encrypted data will has a different length compares to origin data. So the DB field length need to be changed. If the ENCRYPTION_METHODS changed, we have 2 choices:<ul><li>Change the field max length to max of all encrypted data length. e.g. Origin field length is 10. AES encrypted data length is 64. VAULT encrypted data length is 9. The we choose max(64, 9) = 64.</li><li>Use the encrypted data length as configured methods and Raise an exception to notify. “ENCRYPTION_METHODS can not be changed.”</li></ul></li><li>Another problem for data length changing is, in admin panel, the data length validation is not valid anymore. So far no good way to resolve (No place to store the origin length in DB) If we only allow VAULT, this and above 2 issue may not existed. (we keep the filed with fixed length. we do not add prefix.)</li><li>Each access to sensitive data will cause an REST API call to Vault server. This could be potential performance issue.</li></ul><p>— END —</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;We are encrypting sensitive content with AES algorithm and storing them in DB. Now we plan to leverage HashiCorp Vault to do this.&lt;/p&gt;
    
    </summary>
    
      <category term="Architecture &amp; System" scheme="http://blog.samuelchen.net/categories/Architecture-System/"/>
    
    
      <category term="cloud" scheme="http://blog.samuelchen.net/tags/cloud/"/>
    
      <category term="HashiCorp" scheme="http://blog.samuelchen.net/tags/HashiCorp/"/>
    
      <category term="microservice" scheme="http://blog.samuelchen.net/tags/microservice/"/>
    
      <category term="Alibaba Cloud" scheme="http://blog.samuelchen.net/tags/Alibaba-Cloud/"/>
    
      <category term="Vault" scheme="http://blog.samuelchen.net/tags/Vault/"/>
    
      <category term="encryption" scheme="http://blog.samuelchen.net/tags/encryption/"/>
    
  </entry>
  
  <entry>
    <title>Solution Selection for Sensitive Content Storing</title>
    <link href="http://blog.samuelchen.net/solution-selection-for-sensitive-content-storing/"/>
    <id>http://blog.samuelchen.net/solution-selection-for-sensitive-content-storing/</id>
    <published>2019-01-11T11:10:38.000Z</published>
    <updated>2020-06-15T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<p>In “Managed Service for Alibaba Cloud” service project, we have some sensitive data such as secret key, vm password and so on stored in database. To avoid store plain text, we need a solution to encrypt and decrypt sensitive data. </p><a id="more"></a><h2 id="Solutions"><a href="#Solutions" class="headerlink" title="Solutions"></a>Solutions</h2><h3 id="Keystore"><a href="#Keystore" class="headerlink" title="Keystore"></a>Keystore</h3><p>Systems that provide ability to store sensitive key/token/password. Encryption and decryption will handled by the system.</p><ul><li><p>IDM</p></li><li><p>Valut</p></li></ul><p>Need to involve a new system and maintain it. </p><h3 id="Encoding"><a href="#Encoding" class="headerlink" title="Encoding"></a>Encoding</h3><p>Reversible character encoding algorithms. Same algorithm will be used for encryption and decryption.</p><ul><li>HEX, BASE64 (BASE##), UTF8 and etc.</li><li>compaction algorithm such as Huffman Coding, ZIP (Deflate) , JPEG, MPEG and etc.</li><li>etc</li></ul><p>Easy to be decode. </p><h3 id="Abstract-algorithm"><a href="#Abstract-algorithm" class="headerlink" title="Abstract algorithm"></a>Abstract algorithm</h3><p>Irreversible algorithm. Not appropriate for us.</p><ul><li>MD5</li><li>SHA-1, SHA-256</li><li>MAC</li><li>etc.</li></ul><h3 id="Symmetric-encryption"><a href="#Symmetric-encryption" class="headerlink" title="Symmetric encryption"></a>Symmetric encryption</h3><p>Reversible algorithm. Plaint text (data) is encrypted or decrpyted with given private key (shared secret) with same algorithm. <a href="https://en.wikipedia.org/wiki/Symmetric-key_algorithm" target="_blank" rel="noopener">https://en.wikipedia.org/wiki/Symmetric-key_algorithm</a></p><ul><li>DES</li><li>AES</li><li>RC</li><li>etc.</li></ul><p>Need to share the private key.</p><h3 id="Asymmetric-encryption"><a href="#Asymmetric-encryption" class="headerlink" title="Asymmetric encryption"></a>Asymmetric encryption</h3><p>Reversible algorithm. Plaint text (data) is encrypted with public key. The encrypted data is decrypted only with private key. The public key can be openly distributed without compromising security. Encryption and decryption in different way.  <a href="https://en.wikipedia.org/wiki/Public-key_cryptography" target="_blank" rel="noopener">https://en.wikipedia.org/wiki/Public-key_cryptography</a></p><ul><li>RSA</li><li>DSA</li><li>ECC</li><li>etc.</li></ul><h2 id="Anaysis"><a href="#Anaysis" class="headerlink" title="Anaysis"></a>Anaysis</h2><ul><li>Keystore - One more system means one more point need to care the load, failure and so on. Need to communicate between severs even to set/get a property of resource (such as vm property password). </li><li>Vault - Described in <a href="../encrypt-decrypt-and-store-sensitive-content-with-hashicorp-vault">this post</a></li><li>Encoding - Too weak. Easy to be decode.</li><li>Abstract algorithm - Irreversible. Not appropriate.</li><li>Symmetric encryption - Good choice. Need to store the key in separate place. Good solution for encryption and decryption in same system. (e.g. AES)</li><li>Asymmetric encryption - Good choice. Need to maintain 2 keys and store in separate places. It’s not necessary because we have the encryption &amp; decryption in same application. Good solution for separate encryption and decryption. (e.g. RSA)  For RSA, plain text can not be longer than the key.</li></ul><table><thead><tr><th></th><th>Maturity</th><th>Security</th><th>Speed</th><th>Load</th><th>Comment</th></tr></thead><tbody><tr><td>DES</td><td>High</td><td>Low</td><td>Medium High</td><td>Medium</td><td></td></tr><tr><td>AES</td><td>High</td><td>High</td><td>High</td><td>Low</td><td>Replacement of DES</td></tr><tr><td>RSA</td><td>High</td><td>High</td><td>Low</td><td>High</td><td>plaint text can not longger than key</td></tr><tr><td>DSA</td><td>High</td><td>High</td><td>Low</td><td></td><td>Only for digital signature.</td></tr><tr><td>ECC</td><td>Low</td><td>High</td><td>High</td><td>Low</td></tr></tbody></table><p>Above all, we better choose Symmetric encryption <strong>AES</strong>.  And AES is faster and lower load compares to RSA.</p><h2 id="Resolution"><a href="#Resolution" class="headerlink" title="Resolution"></a>Resolution</h2><p>The database server and application server are behind the firewall. And they are in private network. This ensures the architecture level security.</p><h3 id="Key"><a href="#Key" class="headerlink" title="Key"></a>Key</h3><p> Stores in OSS or shared NFS with authorization. Read when application started (only in memory).</p><h3 id="Customer-Alicloud-key-amp-secret"><a href="#Customer-Alicloud-key-amp-secret" class="headerlink" title="Customer Alicloud key &amp; secret"></a>Customer Alicloud key &amp; secret</h3><p>Encrypt it before saving. Decrypt it after loading.</p><h3 id="Virtual-Instance-password-in-parameter"><a href="#Virtual-Instance-password-in-parameter" class="headerlink" title="Virtual Instance password in parameter"></a>Virtual Instance password in parameter</h3><p>Encrypt it before saving. Decrypt it after loading.</p><p>— END —</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;In “Managed Service for Alibaba Cloud” service project, we have some sensitive data such as secret key, vm password and so on stored in database. To avoid store plain text, we need a solution to encrypt and decrypt sensitive data. &lt;/p&gt;
    
    </summary>
    
      <category term="Architecture &amp; System" scheme="http://blog.samuelchen.net/categories/Architecture-System/"/>
    
    
      <category term="cloud" scheme="http://blog.samuelchen.net/tags/cloud/"/>
    
      <category term="microservice" scheme="http://blog.samuelchen.net/tags/microservice/"/>
    
      <category term="Alibaba Cloud" scheme="http://blog.samuelchen.net/tags/Alibaba-Cloud/"/>
    
      <category term="Vault" scheme="http://blog.samuelchen.net/tags/Vault/"/>
    
      <category term="keystore" scheme="http://blog.samuelchen.net/tags/keystore/"/>
    
      <category term="encryption" scheme="http://blog.samuelchen.net/tags/encryption/"/>
    
  </entry>
  
  <entry>
    <title>为2012年中的13寸macbook pro更换固态硬盘SSD并添加内存</title>
    <link href="http://blog.samuelchen.net/Change-SSD-and-add-memory-for-2012-mid-macbook-pro/"/>
    <id>http://blog.samuelchen.net/Change-SSD-and-add-memory-for-2012-mid-macbook-pro/</id>
    <published>2018-11-14T16:55:37.000Z</published>
    <updated>2022-02-03T19:26:34.930Z</updated>
    
    <content type="html"><![CDATA[<p>刚刚给2012年中的13寸MacBook Pro更换了SSD固态硬盘，并且添加了内存，记录一下。</p><a id="more"></a><pre><code>**注意请先断电**</code></pre><h3 id="工具和配件"><a href="#工具和配件" class="headerlink" title="工具和配件"></a>工具和配件</h3><ul><li>十字起子</li></ul><p>钟表手机维修用的十字起子 锥头型号 PH000 用来开外壳以及绝大部分螺丝.<br>网上有些文章说PH00，PH0甚至一般十字起子，这些都不对，大了容易伤螺丝。</p><ul><li>内6角起子</li></ul><p>另外如果要把SSD固态硬盘放到HDD机械硬盘位，那么需要拆掉机械硬盘，这个时候会用到。<br>网上说的一般是T5，这个应该可以，但我用的是T6，也合适。</p><ul><li>光驱位硬盘托架</li></ul><p>市面上一般有两种厚度，9.5mm 和 12.5mm (也有相差零点几个毫米的)，要选择薄的9.5mm这种。<br>接口要选择SATA 3.0，这款2012年中13寸的MacBook Pro支持SATA 3.0。<br>最好选择专门为MacBook Pro设计的，我在挑选的时候发现这种好像比普通的在外延多两个螺丝孔，<br>后面安装的时候会发现这个是必须的固定位。<br>商家有些会送螺丝，或者固定胶条和胶钉，视情况选择，我感觉胶条和胶钉比较好。</p><h3 id="内存"><a href="#内存" class="headerlink" title="内存"></a>内存</h3><p>该款机型内置的是2条1600海士力DDR3内存，电压为标准压1.5v，所以不能买1.25v低电压内存。<br>因此我选购了金士顿的标准压8G-1600单条，毋需买同品牌同大小的内存，频率相同即可，可以节省一条。<br>频率选择不同的应该也可以，但应就高不就低，也就是说高于1600应该是可以的。<br>装好后配置为10G，使用中没发现什么问题。</p><p>安装也很简单，两边的卡子轻推就会自动弹出，插好新的后下压可卡住，网上很多教程。</p><h3 id="SSD固态硬盘"><a href="#SSD固态硬盘" class="headerlink" title="SSD固态硬盘"></a>SSD固态硬盘</h3><p>选择很多，比如三星Samsung EVO860等等，我选择了东芝Toshiba TR200。<br>无他，因为之前用过，还便宜。几个月之前买是380RMB，前两天双11买是236.<br>支持SATA3，SSD固态硬盘可以达到6G速度。</p><p>安装之前要想好是装在光驱位还是机械硬盘位。我建议放到光驱位，原因如下：</p><ul><li>机械硬盘位有自动探测震动的功能，而光驱位靠近喇叭，震动频繁，这样机械硬盘很容易坏</li><li>不必拆卸机械硬盘，少准备一个6角螺丝刀</li><li>原系统可保留（其他方式应也可以保留，但这个几乎无变动，还可以从原系统中安给SSD全新安装新系统）</li><li>最重要的，硬盘托架+机械硬盘 厚度很有可能超过，会造成很大麻烦。</li></ul><p>具体安装过程网上很多教程，我发现有两篇英文的最准确，每个步骤都有，而其他的教程基本上都省略了很多步骤，<br>拆喇叭，摄像头等线的基本都没介绍，这几个步骤很关键。具体步骤不细说，<strong>先拆电源接线</strong>，小心即可。</p><h3 id="系统安装"><a href="#系统安装" class="headerlink" title="系统安装"></a>系统安装</h3><p><strong>首先做好备份</strong>， 方法很多，time machine， 移动硬盘复制，网盘，等等。需要转移整个系统的就用time machine，<br>全新安装系统的就备份自己需要的文档和数据。</p><p>系统安装有几种方式：</p><ul><li>Time Machine 全系统恢复</li><li>从Recover恢复当前系统使用MacOS版本 （开机 command + R + xxx 网上介绍很多）</li><li>从网络安装当前机型支持的最高版本MacOS （同样组合键开机安装，有点旧型号不支持）</li><li>下载安装文件，从原系统中安装</li></ul><p>我使用的是最后这种，比较保险，而且可以选择需要等版本。</p><p>当时准备了3个版本：Sierra，High Sierra，Mojave。很快就放弃了Sierra，因为High Sierra是其升级且更稳定版本，<br>估计性能差不多，High Sierra应该更好。Mojave考虑不太敢装，6年前的机器，怕跑不动。<br>另外还有一个就是Recover的EI Captain，这个还是用的 Macos 文件系统，而上面准备的三种，都升级到了APFS文件系统。<br>APFS是Apple专门为SSD打造的系统，比较新，只经历了2个版本，不知道稳定性如何。<br>最终选择的是Mojave，因为全新安装，打算试试，如果性能太差就抹掉再安装High Sierra。</p><p>后面使用发现这个选择是正确的，虽然Mojave还是第一个版本，但稳定行还不错，而且经过内存升级和更换SSD后，性能也还能接受。</p><p>系统安装好后，自动会使用SSD启动（即使在光驱位），几天运行良好，因此我决定抹掉机械银盘<br>（HDD使用macos 不区分大小写日志文件系统），将其作为数据盘。<br>但恢复分区没有抹掉，里面有EI Captain的恢复镜像，保留以备将来有用。</p><h3 id="系统优化"><a href="#系统优化" class="headerlink" title="系统优化"></a>系统优化</h3><p>因为使用SSD固态硬盘，系统安装好之后，需要配置一下更适合固态硬盘。</p><p>固态硬盘特性是寿命有限制，那么我们需要做这么几件事情来优化</p><ul><li><p>关闭rootless</p><p>  Rootless 具体是什么网上很多，简单说就是限制root的权限来确保系统目录或文件的安全。<br>  有些文章说开启TRIM可能需要关闭rootless，我在开启TRIM时发现不需要，这个因系统而异。<br>  如果后面要移动一些系统目录（比如HOME），或者做开发，也最好关闭。</p><p>  步骤 ：</p><pre><code>* 重启并按住command+r 进入恢复模式* 选择命令行工具，输入`sudo csrutil disable`* 需要重启。</code></pre></li><li><p>开启Trim。</p><p>  Trim是一种均衡固态硬盘读写的技术，使得写入不会总在一个地方。非Apple内置SSD不会自动开启Trim，需要自行开启。<br>  使用命令 <code>sudo trimforce enable</code>, 然后确认即可，可能重启。早期版本比如Yosimate可能需要重置 NVRAM/PRAM，<br>  我是用Mojave没有重置。</p></li><li><p>移动User Home</p><p>  为了减少SSD的使用量以及读写消耗，我将个人用户home目录移动到了机械硬盘。<br>  这个目录移动可以在 <code>设置-&gt;用户与组-&gt;解锁-&gt;右键自己用户-&gt;高级功能</code> 中修改，然后系统自动移动并重启。</p><p>  也可以使用命令完成移动整个User目录</p><pre><code>$sudo ditto /Users /Volumes/Macintosh\ HD/Users$sudo mv /Users /Users.backup $sudo ln -s /Volumes/Macintosh\ HD/Users Users$sudo rm -rf /Users.backup</code></pre></li><li><p>移动其他目录</p><p>  移动临时目录/tmp，因为/tmp是链接到/private/tmp，所以如下： </p><pre><code>$ sudo ditto /private/tmp /Volumes/Macintosh\ HD/private/tmp$ sudo rm -rf /private/tmp$ sudo ln -s /Volumes/Macintosh\ HD/private/tmp /private/tmp</code></pre></li><li><p>修改休眠文件位置 或 关闭休眠</p><ul><li><p>查看休眠配置</p><pre><code>$ pmset -g|grep hibernatehibernatefile        /var/vm/sleepimagehibernatemode        3</code></pre></li><li><p>修改休眠文件位置</p><pre><code>$ sudo pmset -a hibernatefile /Volumes/Macintosh\ HD/var/vm/sleepimage</code></pre></li><li><p>关闭休眠</p><p>Suspend to RAM ——&gt; 对应的hibernatemode：0；<br>Suspend to RAM+Disk ——&gt; 对应的hibernatemode：3<br>Suspend to Disk ——&gt; 对应的hibernatemode：5；</p><pre><code>$ sudo pmset -a hibernatemode 0</code></pre></li></ul></li></ul><ul><li><p>关闭文件最后访问时间</p><p>  <a href="http://junqiu.lofter.com/post/1d084679_5ef95d0" target="_blank" rel="noopener">http://junqiu.lofter.com/post/1d084679_5ef95d0</a></p><pre><code>$ sudo vi /Library/LaunchDaemons/com.nullvision.noatime.plist</code></pre><p>  编辑为如下内容</p><pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;&lt;plist version=&quot;1.0&quot;&gt;    &lt;dict&gt;        &lt;key&gt;Label&lt;/key&gt;        &lt;string&gt;com.noatime&lt;/string&gt;        &lt;key&gt;ProgramArguments&lt;/key&gt;        &lt;array&gt;            &lt;string&gt;mount&lt;/string&gt;            &lt;string&gt;-vuwo&lt;/string&gt;            &lt;string&gt;noatime&lt;/string&gt;            &lt;string&gt;/&lt;/string&gt;        &lt;/array&gt;        &lt;key&gt;RunAtLoad&lt;/key&gt;&lt;true/&gt;    &lt;/dict&gt;&lt;/plist&gt;</code></pre><p>  然后设置权限</p><pre><code>$ sudo chown root:wheel /Library/LaunchDaemons/com.noatime.plist$ sudo chmod 644 /Library/LaunchDaemons/com.noatime.plist</code></pre><p>  重启后，使用命令 <code>mount | grep /</code> 查看，可以看到多了一个<code>noatime</code>属性</p><p>  使用前</p><pre><code>/dev/disk2s1 on / (apfs, local, journaled)</code></pre><p>  使用后</p><pre><code>/dev/disk2s1 on / (apfs, local, journaled, noatime)</code></pre></li></ul><p>— END —</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;刚刚给2012年中的13寸MacBook Pro更换了SSD固态硬盘，并且添加了内存，记录一下。&lt;/p&gt;
    
    </summary>
    
      <category term="Life" scheme="http://blog.samuelchen.net/categories/Life/"/>
    
    
      <category term="MacBook" scheme="http://blog.samuelchen.net/tags/MacBook/"/>
    
      <category term="upgrade" scheme="http://blog.samuelchen.net/tags/upgrade/"/>
    
  </entry>
  
  <entry>
    <title>API Gateway by Fabio &amp; Consul</title>
    <link href="http://blog.samuelchen.net/api-gateway-by-fabio-n-consul/"/>
    <id>http://blog.samuelchen.net/api-gateway-by-fabio-n-consul/</id>
    <published>2018-02-28T08:21:23.000Z</published>
    <updated>2020-06-15T13:42:12.000Z</updated>
    
    <content type="html"><![CDATA[<p>Fabio is a HTTP router app written by Go language. It is Zero-configuration and simple to deploy. As official document mentioned, “It delivers 23.000 req/sec every day since Sep 2015 without problems”. It’s written and maintained by Frank Schroeder at eBay in Amsterdam.</p><a id="more"></a><h2 id="Installation"><a href="#Installation" class="headerlink" title="Installation"></a>Installation</h2><p><em>Check <a href="/Service-Discover-by-Consul">Service Discover by Consul</a> for installation of Consul</em></p><ul><li>Project pages<ul><li><a href="https://fabiolb.net" target="_blank" rel="noopener">https://fabiolb.net</a> (<a href="https://fabiolb.net/" target="_blank" rel="noopener">https://fabiolb.net/</a>)</li><li><a href="https://github.com/fabiolb/fabio" target="_blank" rel="noopener">https://github.com/fabiolb/fabio</a></li><li><a href="https://www.consul.io/" target="_blank" rel="noopener">https://www.consul.io/</a></li></ul></li></ul><p>Fabio is a single file app. You just download the executable for your OS from its release page (<a href="https://github.com/fabiolb/fabio/releases" target="_blank" rel="noopener">https://github.com/fabiolb/fabio/releases</a>) or use <code>brew install fabio</code> (MacOS) or <code>go get github.com/fabiolb/fabio</code> (Golang) to download to local. Rename it to <code>fabio</code> and add executing privilege.</p><h2 id="Configuration"><a href="#Configuration" class="headerlink" title="Configuration"></a>Configuration</h2><p>Fabio is zero-conf app. Which means you need almost no configuration. If you deploy it on the machine where you Consul deployed, it will automatically find service and register health check on it (Consul default localhost:8500)</p><p>Check the Fabio Wiki: <a href="https://github.com/fabiolb/fabio/wiki/Quickstart" target="_blank" rel="noopener">https://github.com/fabiolb/fabio/wiki/Quickstart</a></p><h3 id="How-a-registered-service-in-Consul-will-be-listed-in-Fabio-routers"><a href="#How-a-registered-service-in-Consul-will-be-listed-in-Fabio-routers" class="headerlink" title="How a registered service in Consul will be listed in Fabio routers?"></a>How a registered service in Consul will be listed in Fabio routers?</h3><p>Use a tag to identify a service in Consul. It will be recognized as a router.<br>e.g. the following is a service registry config file.</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">"service"</span>: &#123;</span><br><span class="line">    <span class="attr">"name"</span>: <span class="string">"jenkins"</span>, <span class="attr">"port"</span>: <span class="number">8080</span>,</span><br><span class="line">    <span class="attr">"tags"</span>: [<span class="string">"propel-/jenkins"</span>],</span><br><span class="line">    <span class="attr">"address"</span>: <span class="string">"ec4t01624.itcs.entsvcs.net"</span>,</span><br><span class="line"><span class="attr">"port"</span>: <span class="number">8080</span>,</span><br><span class="line">    <span class="attr">"check"</span>: &#123;</span><br><span class="line">      <span class="attr">"http"</span>: <span class="string">"http://ec4t01624.itcs.entsvcs.net:8080/jenkins/"</span>,</span><br><span class="line">      <span class="attr">"interval"</span>: <span class="string">"10s"</span>,</span><br><span class="line">      <span class="attr">"timeout"</span>: <span class="string">"1s"</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Note that <code>“tags”: [“propel-/jekins”]</code>. It means this is a service for Fabio. <code>propel-</code> is the prefix of tag to identify (which default is <code>urlprefix-</code>. You can change it by <code>-registry.consul.tagprefix “propel-”</code>.) <code>/jekins</code> means the endpoint to the service.</p><p>Visit <a href="http://myconsul:8500/" target="_blank" rel="noopener">http://myconsul:8500/</a> and check “service” tab, you will see registered service and the tags.<br><img src="consul-dashboard.jpg" alt></p><p>Visit <a href="http://myfabio:9998/" target="_blank" rel="noopener">http://myfabio:9998/</a>, you will see the routers (with red rectangle marked)<br><img src="fabio-routing.jpg" alt></p><p>At last, visit <a href="http://myfabio:9999/jenkins" target="_blank" rel="noopener">http://myfabio:9999/jenkins</a> (/${tag}). You will be routed to <a href="http://ec4t01624.itcs.entsvcs.net:8080/jenkins" target="_blank" rel="noopener">http://ec4t01624.itcs.entsvcs.net:8080/jenkins</a> .</p><h3 id="How-if-I-need-to-route-to-a-host-without-a-path"><a href="#How-if-I-need-to-route-to-a-host-without-a-path" class="headerlink" title="How if I need to route to a host without a path"></a>How if I need to route to a host without a path</h3><p>e.g. my tomcat server at <a href="http://ec4t01624.itcs.entsvcs.net:8080/" target="_blank" rel="noopener">http://ec4t01624.itcs.entsvcs.net:8080/</a></p><p>You need to set the tag with an option <code>strip=/tomcat</code>. It means the router will strip <code>/tomcat</code> from url path when routing. See the blue rectangle mark in the above 2nd screenshot (<code>option</code> column of tomcat). You will see it in <code>Consul</code> dashboard as below.<br><img src="consul-service.jpg" alt></p><p>Visit <a href="http://myfabio:9999/tomcat/" target="_blank" rel="noopener">http://myfabio:9999/tomcat/</a>. It will route to <a href="http://ec4t01624.itcs.entsvcs.net:8080/" target="_blank" rel="noopener">http://ec4t01624.itcs.entsvcs.net:8080/</a> . The <code>/tomcat</code> in url path is removed. (note the last <code>/</code> is required. Check the <code>source</code> column in above 2nd screenshot.)</p><p>The service registry config file in Consul is:</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">"services"</span>: [&#123;</span><br><span class="line">    <span class="attr">"name"</span>: <span class="string">"tomcat"</span>,</span><br><span class="line">    <span class="attr">"tags"</span>:[<span class="string">"propel-/tomcat/ strip=/tomcat"</span>],</span><br><span class="line">    <span class="attr">"address"</span>: <span class="string">"ec4t01624.itcs.entsvcs.net"</span>,</span><br><span class="line">    <span class="attr">"port"</span>: <span class="number">8080</span>,</span><br><span class="line">    <span class="attr">"check"</span>: &#123;</span><br><span class="line">      <span class="attr">"http"</span>: <span class="string">"http://ec4t01624.itcs.entsvcs.net:8080"</span>,</span><br><span class="line">      <span class="attr">"interval"</span>: <span class="string">"10s"</span>,</span><br><span class="line">      <span class="attr">"timeout"</span>: <span class="string">"3s"</span>,</span><br><span class="line">      <span class="attr">"status"</span>: <span class="string">"passing"</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="Run"><a href="#Run" class="headerlink" title="Run"></a>Run</h2><p>Just run <code>$ fabio</code> in terminal.</p><p>You may use –help to check the arguments. Or use a <code>fabio.properties</code> file as configuration.</p><p>To run with prefix, <code>$ fabio -registry.consul.tagprefix propel-</code></p><h3 id="Run-as-service"><a href="#Run-as-service" class="headerlink" title="Run as service"></a>Run as service</h3><pre><code>TODO</code></pre><h2 id="Other"><a href="#Other" class="headerlink" title="Other"></a>Other</h2><ul><li>When I test with Apache Benchmark (ab), if the concurrent clients number sets to 500, it will occurs <code>socket too many open files</code> error. You need to use <code>ulimited -n 65535</code> to fix it.</li></ul><ul><li>Check the log, you will see which service is captured.</li></ul><p>— END —</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Fabio is a HTTP router app written by Go language. It is Zero-configuration and simple to deploy. As official document mentioned, “It delivers 23.000 req/sec every day since Sep 2015 without problems”. It’s written and maintained by Frank Schroeder at eBay in Amsterdam.&lt;/p&gt;
    
    </summary>
    
      <category term="Architecture &amp; System" scheme="http://blog.samuelchen.net/categories/Architecture-System/"/>
    
    
      <category term="cloud" scheme="http://blog.samuelchen.net/tags/cloud/"/>
    
      <category term="deployment" scheme="http://blog.samuelchen.net/tags/deployment/"/>
    
      <category term="Consul" scheme="http://blog.samuelchen.net/tags/Consul/"/>
    
      <category term="HashiCorp" scheme="http://blog.samuelchen.net/tags/HashiCorp/"/>
    
      <category term="microservice" scheme="http://blog.samuelchen.net/tags/microservice/"/>
    
      <category term="service discovery" scheme="http://blog.samuelchen.net/tags/service-discovery/"/>
    
      <category term="cluster" scheme="http://blog.samuelchen.net/tags/cluster/"/>
    
      <category term="API gateway" scheme="http://blog.samuelchen.net/tags/API-gateway/"/>
    
      <category term="Fabio" scheme="http://blog.samuelchen.net/tags/Fabio/"/>
    
  </entry>
  
  <entry>
    <title>Machine Learning Memo 1</title>
    <link href="http://blog.samuelchen.net/Machine-Learning-Memo-1/"/>
    <id>http://blog.samuelchen.net/Machine-Learning-Memo-1/</id>
    <published>2017-12-12T07:19:20.000Z</published>
    <updated>2022-02-03T19:26:34.930Z</updated>
    
    <content type="html"><![CDATA[<p>最近开始看Andrew Ng 的 <a href="https://www.coursera.org/learn/machine-learning" target="_blank" rel="noopener">Machine Learning 系列课程</a>，记录一下体会。</p><a id="more"></a><h3 id="Machine-Learning-学习笔记-第一周"><a href="#Machine-Learning-学习笔记-第一周" class="headerlink" title="Machine Learning 学习笔记 - 第一周"></a>Machine Learning 学习笔记 - 第一周</h3><p>重要关键词：Supervised, Unsupervised, Regression, Classfication, Features</p><p>机器学习主要分为有监管的(supervised)和无监管(两类).<br>有监管的基本上分为回归的(regression)和聚类(classfication)两种。<br>无监管的主要是用来分类。</p><p>假如有一件事情来了，如何来区分它适用哪一种方式？我总结了一点。</p><ul><li>Supervised (由人来<strong>监管或者指导</strong>已知答案的对错，从而判度未知答案或者预测）<ul><li>Regression. 根据已有的历史数据来<strong>预测(predict)</strong>将来某个点的数据。例如，天气预测，股票预测。</li><li>Classfication. 根据已有的历史数据来判断将来具有某些<strong>特征(feature)</strong>的某个数据，<strong>是否(weather or not)</strong> 某种状态。例如，某个年龄、某种肿瘤大小的患者是否(yes/no)是恶性的。再如，垃圾邮件标注及判断。</li></ul></li><li>Unsupervised<ul><li>从给定的历史数据来<strong>判断哪些数据是聚集在一起(在坐标轴上)</strong>，将这一部分数据归为一类，从而将所有数据归纳为几个分类(在之前，人并不知道结果）。例如，文章的分类，声音的剥离。</li></ul></li></ul><p>Feature 是指特征，表现为坐标轴，例如 判断肿瘤一例中的年龄和肿瘤大小就是两个特征。特征数量足够以及合适（并不是多）才能更准确的学习。</p><p>— END —</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;最近开始看Andrew Ng 的 &lt;a href=&quot;https://www.coursera.org/learn/machine-learning&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Machine Learning 系列课程&lt;/a&gt;，记录一下体会。&lt;/p&gt;
    
    </summary>
    
      <category term="Programming" scheme="http://blog.samuelchen.net/categories/Programming/"/>
    
    
      <category term="supervised" scheme="http://blog.samuelchen.net/tags/supervised/"/>
    
      <category term="unsupervised" scheme="http://blog.samuelchen.net/tags/unsupervised/"/>
    
      <category term="classfication" scheme="http://blog.samuelchen.net/tags/classfication/"/>
    
      <category term="regression" scheme="http://blog.samuelchen.net/tags/regression/"/>
    
      <category term="feature" scheme="http://blog.samuelchen.net/tags/feature/"/>
    
      <category term="course" scheme="http://blog.samuelchen.net/tags/course/"/>
    
      <category term="memo" scheme="http://blog.samuelchen.net/tags/memo/"/>
    
      <category term="machine learning" scheme="http://blog.samuelchen.net/tags/machine-learning/"/>
    
  </entry>
  
  <entry>
    <title>How to Setup Kafka Web Console</title>
    <link href="http://blog.samuelchen.net/how-to-setup-kafka-web-console/"/>
    <id>http://blog.samuelchen.net/how-to-setup-kafka-web-console/</id>
    <published>2014-04-24T07:15:11.000Z</published>
    <updated>2022-02-03T19:26:34.930Z</updated>
    
    <content type="html"><![CDATA[<p>“Kafka Web Console” is a open source monitor tool for <code>Kafka</code>. </p><a id="more"></a><p>This project is hosted at <a href="https://github.com/claudemamo/kafka-web-console" target="_blank" rel="noopener">https://github.com/claudemamo/kafka-web-console</a>. It’s a very simple console that only suit for learning Kafka purpose. (Until when the post written.)</p><ul><li><p>Install Play Framework.</p><ul><li>Download here <a href="http://www.playframework.com/download" target="_blank" rel="noopener">http://www.playframework.com/download</a></li><li>Unzip to /path/to/play</li><li>Build Play. /path/to/play/framework/build</li></ul></li><li><p>Install Kafka-web-console.</p><ul><li>git clone <a href="https://github.com/claudemamo/kafka-web-console.git" target="_blank" rel="noopener">https://github.com/claudemamo/kafka-web-console.git</a>  /path/to/kafka-web-console</li><li>(or download the stable zip from <a href="https://github.com/claudemamo/kafka-web-console/releases" target="_blank" rel="noopener">https://github.com/claudemamo/kafka-web-console/releases</a>)</li></ul></li><li><p>Run the server</p><ul><li>Enable port 9000 for the server.</li><li>cd /path/to/kafka-web-console</li><li>/path/to/play/play start</li><li>Then the web console is servicing on port 9000.</li></ul></li><li><p>Configuration</p><ul><li><p>register zookeeper<br><img src="img1.png" alt></p></li><li><p>Check status to see if connected<br><img src="img2.png" alt></p></li></ul></li></ul><ul><li>“Database xxx needs evolution!” - Solution for database is not initialized.<ul><li>use “play -DapplyEvolutions.default=true” to start. </li><li>Or add “applyEvolutions.default=true” in conf/application.conf </li></ul></li></ul><p>— END —</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;“Kafka Web Console” is a open source monitor tool for &lt;code&gt;Kafka&lt;/code&gt;. &lt;/p&gt;
    
    </summary>
    
      <category term="Utility" scheme="http://blog.samuelchen.net/categories/Utility/"/>
    
    
      <category term="configuration" scheme="http://blog.samuelchen.net/tags/configuration/"/>
    
      <category term="deployment" scheme="http://blog.samuelchen.net/tags/deployment/"/>
    
      <category term="MQ" scheme="http://blog.samuelchen.net/tags/MQ/"/>
    
      <category term="monitor" scheme="http://blog.samuelchen.net/tags/monitor/"/>
    
      <category term="Kafka" scheme="http://blog.samuelchen.net/tags/Kafka/"/>
    
      <category term="open source" scheme="http://blog.samuelchen.net/tags/open-source/"/>
    
  </entry>
  
  <entry>
    <title>Ubuntu12 虚拟机网络配置</title>
    <link href="http://blog.samuelchen.net/ubuntu12-vm-network-config/"/>
    <id>http://blog.samuelchen.net/ubuntu12-vm-network-config/</id>
    <published>2012-06-21T11:09:05.000Z</published>
    <updated>2022-02-03T19:26:34.930Z</updated>
    
    <content type="html"><![CDATA[<pre><code>后来，了解了更多的方法，这种方法并不是一个比较好的方法，但仍不失为一个简单有效的方法。</code></pre><p>用VM Player 4.0装了Ubuntu 12 server，然后复制了几个组成局域网来使用，发现了一些问题，网上基本上找不到完整的解决方法，这里记录下来。</p><a id="more"></a><h2 id="Mac-地址"><a href="#Mac-地址" class="headerlink" title="Mac 地址"></a>Mac 地址</h2><p>复制的虚机Mac 地址都是相同的，组网会有问题，所以需要改过来。</p><p>首先是修改VM Setting，可以生成一个新的Mac地址，把它记录下来，假设是<br><code>00:AA:BB:CC:DD:EE</code> 。<br>网上的方法主要是</p><pre class="lang:default decode:true">sudo ifconfig eth0 down  #停掉网卡sudo ifconfig eth0 hw ether 00:AA:BB:CC:DD:EE   #改macsudo ifconfig eth0 up     #起网卡sudo /etc/init.d/networking restart  #重启网络</pre>但是，这样是不成的（至少在这次），重启以后会失效，又变回原来的。网上给出的方案是在 `/etc/network/if-pre-up.d/` 中添加`ifconfig eth0 hw ether 00:AA:BB:CC:DD:EE`，但我试过了是不行的。另外有一种方法就是修改 `/etc/rc.local` 每次启动修改，但这种方法不太爽。所以，最终的方案是：在 VM Setting 中删除掉 Network Adpater，然后再重启重新添加一个。就这么简单，思路别被局限了。<!--more-->## 机器名复制以后的机器，名字都是一样，打算取名为vm-ubuntu1, vm-ubuntu2, vm-ubuntu3... 所以得逐个修改。首先 `hostname vm-ubuntu2` 是不能保存的，重启后又还原，所以得修改`/etc/hostname`，内容就一行，`vm-ubuntu2`其次，光改了名字，从其他的机器是ping不到的，所以我们需要修改 `/etc/hosts` 来把所有的机器都列出来。<pre class="lang:default decode:true" title="hosts">127.0.0.1   localhost192.168.48.142  vm-ubuntu1192.168.48.156  vm-ubuntu2192.168.48.148  vm-ubuntu3</pre>将 hosts 文件复制到所有的虚拟机（你也可以使用rsync同步），这样就可以通过名字互通了。## 静态IP上面这样做了之后，会有一个问题，就是DHCP重启之后IP会变，名字就失效了，所以需要改成静态IP。很简单，先 ifconfig 查看一下 当前的 网关和掩码，<pre class="lang:default decode:true">Link encap:Ethernet  HWaddr 00:0c:29:1f:2a:fc          inet addr:192.168.48.142  Bcast:192.168.48.255  Mask:255.255.255.0</pre>网关是 `192.168.48.255`， 掩码是 `255.255.255.0`，同时可以看到Mac已经变了(HWaddr就是）然后修改 `/etc/network/interfaces` 就可以了，<pre class="lang:default decode:true">auto eth0iface eth0 inet dhcp</pre>改为<pre class="lang:default decode:true">auto eth0iface eth0 inet staticaddress 192.168.48.100netmask 255.255.255.0gateway 192.168.48.255</pre>这儿有个陷阱，就是 VM 的 网关实际上并不是 192.168.xx.255，而是window下看到的 VMware Network Adapter VMnet8 的 IP，一般是 192.168.xx.2，可以尝试 192.168.xx.1 或者 192.168.xx.2，所以真实的应该是<pre class="lang:default decode:true">auto eth0iface eth0 inet staticaddress 192.168.48.101netmask 255.255.255.0gateway 192.168.48.2</pre>注意：我们不要使用192.168.xx.1 或者 2 来作为虚机的IP，这些都保留了，安全起见，用100之后的。最后 sudo reboot，重启之后就可以联网了。## DNS 域名解析上面设好了后，内网基本没问题，但是连外网可能会碰到问题，域名解析不了（我碰到了），所以需要设置DNS。网上的方法，有一种是修改 `/etc/network/interfaces` 加上 nameserver<pre class="lang:default decode:true">auto eth0iface eth0 inet staticaddress 192.168.48.101netmask 255.255.255.0gateway 192.168.48.2nameserver 8.8.8.8</pre>这个貌似没有用，最后有用的方法是，修改 `/etc/resolveconf/resolve.conf.d/base`，加上 nameserver 就可以了<pre class="lang:default decode:true">nameserver 192.168.48.2nameserver 8.8.8.8nameserver 8.8.4.4</pre><p>— END —</p>]]></content>
    
    <summary type="html">
    
      &lt;pre&gt;&lt;code&gt;后来，了解了更多的方法，这种方法并不是一个比较好的方法，但仍不失为一个简单有效的方法。
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;用VM Player 4.0装了Ubuntu 12 server，然后复制了几个组成局域网来使用，发现了一些问题，网上基本上找不到完整的解决方法，这里记录下来。&lt;/p&gt;
    
    </summary>
    
      <category term="Architecture &amp; System" scheme="http://blog.samuelchen.net/categories/Architecture-System/"/>
    
    
      <category term="configuration" scheme="http://blog.samuelchen.net/tags/configuration/"/>
    
      <category term="Linux" scheme="http://blog.samuelchen.net/tags/Linux/"/>
    
      <category term="Ubuntu" scheme="http://blog.samuelchen.net/tags/Ubuntu/"/>
    
      <category term="VM" scheme="http://blog.samuelchen.net/tags/VM/"/>
    
      <category term="network" scheme="http://blog.samuelchen.net/tags/network/"/>
    
  </entry>
  
  <entry>
    <title>改变使用方式，重定义一个行业</title>
    <link href="http://blog.samuelchen.net/redefine-industry-by-changing-usage/"/>
    <id>http://blog.samuelchen.net/redefine-industry-by-changing-usage/</id>
    <published>2012-03-10T17:10:00.000Z</published>
    <updated>2022-02-03T19:26:34.930Z</updated>
    
    <content type="html"><![CDATA[<p>一直比较喜欢和敬佩能改变或重新定义一个行业一个产业的人和公司，Bill Gates 改变了人们使用电脑的方法，Jobs 重新定义了手机，任天堂将游戏从桌面带到了屏幕，又从沙发带到了客厅，从家里带到了身上，facebook 把社交带到了电脑（准确来说，虚拟人生很早就在做这个事情），Google改变了互联网的入口，亚马逊、Google 等改变了计算方式，……</p><a id="more"></a><p>今天，互联网和移动终端，我们都知道，正在改变这个行业，大家或多或少，或清晰或朦胧的感受到、预见到那些正在以及可能产生的变化，也一直在寻找，我也一直在思考，到底会是怎样。也许有一天，只是一只手指，轻轻的触碰到了那一点，刷的一下，就豁然开朗。</p><p>一直在思考，究竟我们能改变什么？上面那些变化，都是大的公司，在强有力的支持下做出的（除了facebook），也许一个小公司小团队很难做到，但谁知道呢。</p><p>云和端，云很重要，但它实际上是一个载体，就好比互联网，再怎么发展，也是一个工具。而云就是各种业务，应用的一个载体，或许会有一天有天翻地覆的变化，但现在，我能看到的，云是一个很重要的基础设施，要想从这上面想象变化，暂时还没有突破口。</p><p>而端，或者说客户端、消费端，由其表现形式，已经能呈现出非常丰富的变化。而最有可能重新定义的就是软件/应用的消费方式。比如，可能是一个冰箱同步你的菜谱并自动调温，可能是一个闹钟同步你的日程还报出内容。手机端，是一种设备，由于各家巨头都看到了，它也是表现能力非常强的一种设备，正在改变人们消费数字产品的方式，从桌面带到了街头。</p><p>由于其他的设备的发展还不很明朗，所以我想谈谈手机（平板，智能手持设备）可能的带来的改变。</p><p>那么手机有哪些特点？</p><ul><li>首先我们第一个想到的肯定是移动能力</li><li>其次是小尺寸的屏幕（视觉输出）</li><li>接着是加入的GPS定位能力（地理方位输入）</li><li>再就是拍照、摄像（视觉输入）</li><li>还有重力感应（方向和速度输入）</li><li>Siri让我们想起了手机还有语音输入的能力（是不是很奇怪，手机一直都能通话，但这么久才有这个功能，语音识别技术早在上世纪90年代就有了）</li><li>另外还有指南，湿度，高度识别等等（方位，湿度，温度，高度的输入等）<br>注意我第一段说的那些改变，基本上都不是技术上的革命，而是使用方法的革命。就拿Siri来说，典型的旧瓶装新酒，语音识别+wolfalpha+LBS+Schedual 等等，都是早已出现的技术。</li></ul><p>所以我想说，最重要的是方式的改变。借着手机这么丰富的传感功能，也许我们能探索到一些改变某件事情的方法，将互联网和传统结合，走出点新路。</p><p>就拿阅读这件事情来说，什么是阅读？阅读什么？为什么阅读？什么时间阅读？什么位置阅读？什么天气阅读？文字、图片、视频可以阅读大家都知道，但声音能阅读吗？关系能阅读吗？知识能阅读，能力能阅读吗？善恶能阅读吗？阅读能变成游戏吗？阅读能传递吗？无数个想法。Kindle正在改变阅读的载体，阅读的方法呢，也许将来是直接注射的，就好似嫁衣神功一般。</p><p>思想风暴，想想看阅读和手机传感结合能有什么方式？</p><ul><li>阅读内容的改变。除了文字和图片，视频也是可以阅读的，但其他的阅读，受限于内容和表现形式暂时没有想到更好的。视频的阅读，除了播放之外，１）可以拆分成图片＋字幕的方式像漫画一样阅读。２）可以用语音视频读出视频内容，以文字方式阅读。３）看视频的时候同时阅读视频的相关信息比如导演，主演，内容介绍，评论等（已经有网站把评论作为视频的字幕在上下两侧飞过）。总的来说，视频是另外一种内容消费方式，和阅读挂钩丧失了原有的魅力。</li><li>文字与图片的阅读，小屏幕的限制解除，重新排版，转换格式</li><li>阅读的时候看看附近的人都在阅读什么</li><li>看看当地的新闻</li><li>旅游地的文字资料</li><li>长途驾驶对地标照相，自动产生路书并读出来</li><li>两人站在一起晃晃手机就交换了阅读内容</li><li>拍摄报纸一角剪报，识别，存档，日期地点等</li><li>路上看到个海报，拍下来，识别后，自动为你找到相关内容随身看</li><li>平板的阅读方式又和手机不同<br>总的来说，阅读是一种输出的应用，对输入的要求较少，如何利用传感输入可以是一个思路。更进一步的是改变设备的输入输出方式，比如全息，当然这个在技术上和产业实力上都不是一个小事。现在这么多人和企业都在做手机和移动设备，除了一些跟着捞一把的小企业，相信大多都是看到了这些。</li></ul><p>其他的，比如内容的存储，存的越多，手机抖的越厉害。比如有CMS和CRM，为什么不能有RMS，好过现在通讯录。再有，有游戏，有SNS游戏，有MUD，为什么不能有社交关系地理位置的轻游戏或者RMS，比如根据高度差，根据甩手机的重力程度，来攻击，或者不叫攻击叫骚扰，你的朋友（一个同事介绍的LBS游戏给的灵感）。根据通话、短信频率确定关系远近，等等等等。</p><p>– 随想。</p><p>— END —</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;一直比较喜欢和敬佩能改变或重新定义一个行业一个产业的人和公司，Bill Gates 改变了人们使用电脑的方法，Jobs 重新定义了手机，任天堂将游戏从桌面带到了屏幕，又从沙发带到了客厅，从家里带到了身上，facebook 把社交带到了电脑（准确来说，虚拟人生很早就在做这个事情），Google改变了互联网的入口，亚马逊、Google 等改变了计算方式，……&lt;/p&gt;
    
    </summary>
    
      <category term="Industry" scheme="http://blog.samuelchen.net/categories/Industry/"/>
    
    
      <category term="IT" scheme="http://blog.samuelchen.net/tags/IT/"/>
    
  </entry>
  
  <entry>
    <title>下一代互联网初见端倪</title>
    <link href="http://blog.samuelchen.net/next-gen-internet/"/>
    <id>http://blog.samuelchen.net/next-gen-internet/</id>
    <published>2011-06-17T16:26:00.000Z</published>
    <updated>2022-02-03T19:26:34.930Z</updated>
    
    <content type="html"><![CDATA[<p>现在的互联网，以及所谓的物联网，争的是两块，一块是服务端，也就是云端，另一块是终端。</p><p>云端现在是Amazon, Google暂时领先于基础架构领域，MS, Apple 处于追赶之中，Facebook/Twitter则领先于SNS（此SNS含义相当广，包括身份，信用，关系，服务，应用等等）方面。传统厂商如IBM, HP基于其固有的优势，大力推广所谓私有云，实质是企业cluster，在下一代互联网中已经落后一步。</p><p>而终端则是Apple，Google 和 MS 三足鼎立。iOS和Android，已经成为了移动领域事实上的领头羊，MS在桌面的固有优势以及家庭媒体中的发力，使其保持在第一梯队中。而HP，虽然购买了3Par, Palm/webos，但依然未能表现出足够的进取。其他厂商，目前看来，只是陪太子读书的角色。</p><p>— END —</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;现在的互联网，以及所谓的物联网，争的是两块，一块是服务端，也就是云端，另一块是终端。&lt;/p&gt;
&lt;p&gt;云端现在是Amazon, Google暂时领先于基础架构领域，MS, Apple 处于追赶之中，Facebook/Twitter则领先于SNS（此SNS含义相当广，包括身份，
      
    
    </summary>
    
      <category term="Industry" scheme="http://blog.samuelchen.net/categories/Industry/"/>
    
    
      <category term="cloud" scheme="http://blog.samuelchen.net/tags/cloud/"/>
    
      <category term="internet" scheme="http://blog.samuelchen.net/tags/internet/"/>
    
  </entry>
  
  <entry>
    <title>Python 的编码，关于 Encode, Decode 的简单原则</title>
    <link href="http://blog.samuelchen.net/simple-principle-for-encode-decode-in-python/"/>
    <id>http://blog.samuelchen.net/simple-principle-for-encode-decode-in-python/</id>
    <published>2011-04-15T07:14:00.000Z</published>
    <updated>2022-02-03T19:26:34.930Z</updated>
    
    <content type="html"><![CDATA[<p>Python 中 encoding 的处理其实已经很简单了，根据我这近一个月来用python的经验，有一个简单的原则可以作为参考。</p><a id="more"></a><p>基于python 2.7</p><ol><li>类型要清楚， unicode 不是 str</li><li>decode 之后的结果都是 unicode</li><li>encode 之后的结果都是 str，其编码是你encode的参数</li><li>输出一律用 str</li><li>存取一律用 unicode</li><li>应用入口重设默认编码 <code>sys.setdefaultencoding(&#39;utf-8&#39;)</code> （记得需要<code>reload(sys)</code>） </li></ol><p>简单按照这个原则，编码基本上就不会错了。</p><p>举个例子，有个GBK编码的文件 name.txt，每行一个人名，现在要处理</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> line <span class="keyword">in</span> open(<span class="string">'name.txt'</span>).readlines():</span><br><span class="line">  <span class="keyword">print</span> line <span class="comment"># 这时候 line 都是 gbk 的 </span></span><br><span class="line">  str x = line.decode(<span class="string">'gbk'</span>) <span class="comment"># 转成 unicode </span></span><br><span class="line">          <span class="comment">#(建议这么做，原则：但凡输入的，一律转换成unicode后处理)</span></span><br><span class="line">  <span class="keyword">print</span> x <span class="comment"># 输出 unicode (不建议这么做)</span></span><br><span class="line">  <span class="keyword">print</span> x.encode(<span class="string">'utf-8'</span>) <span class="comment"># 输出 str (建议这么做，原则：但凡输出，一定编码成str)</span></span><br><span class="line">  store_to_db(x) <span class="comment"># 这时候存的都是unicode </span></span><br><span class="line">  my_str = x.encode(<span class="string">'big5'</span>) <span class="comment"># 转成 big5了 </span></span><br><span class="line">  <span class="keyword">print</span> m_str <span class="comment"># 输出的是 big5 的 str</span></span><br></pre></td></tr></table></figure><p>此外，encode 的时候不一定会成功，这时候会raise一个exception，这是因为 encode 还有一个参数用来控制encode失败后的处理，default是strict，也就是抛异常。</p><p>你可以用 <code>encode(src, &#39;replace&#39;)</code> 来处理，replace就表示碰到转不了的，用问号<code>&#39;?&#39;</code>来代替，而不是抛异常。</p><p>具体用法查文档。</p><p>同样，输出的时候，输出流也需要有编码。比如stdout默认是ascii的，而你要输出unicode，就需要得到一个基于unicode的输出流，<code>output = codecs.getwriter(&#39;utf-8&#39;)(sys.stdout)</code></p><p>— END —</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Python 中 encoding 的处理其实已经很简单了，根据我这近一个月来用python的经验，有一个简单的原则可以作为参考。&lt;/p&gt;
    
    </summary>
    
      <category term="Programming" scheme="http://blog.samuelchen.net/categories/Programming/"/>
    
    
      <category term="Python" scheme="http://blog.samuelchen.net/tags/Python/"/>
    
      <category term="encoding" scheme="http://blog.samuelchen.net/tags/encoding/"/>
    
  </entry>
  
</feed>
